From d5f6d59b0e7e0ea9fdbb0f587933395a51ce9eff Mon Sep 17 00:00:00 2001
From: Robert Fratto <robertfratto@gmail.com>
Date: Wed, 3 Apr 2024 09:54:36 -0400
Subject: [PATCH] misc: finalize asset names for Linux (#107)

Finalizes asset names so that all of the following are true:

* The published binary is named `alloy-linux-ARCH`
* The default config file path (when an installer is used or in Docker)
  is `/etc/alloy/config.alloy`
* The default data storage path (when an installer is used or in Docker)
  is `/var/lib/alloy/data`
* The system package name is `alloy` and it is installed as a service
  called `alloy`.
* When an installer is used, the service runs as a user `alloy` and
  user group `alloy`.
* For RPM installs, the environment file is stored at
  `/etc/sysconfig/alloy`
* For DEB installs, the environment file is stored at
  `/etc/default/alloy`
---
 Dockerfile                                    |  6 ++++-
 Makefile                                      |  4 +++
 .../alloy_linux_packages_test.go              | 19 ++++++++-----
 packaging/alloy.alloy                         | 27 -------------------
 packaging/config.alloy                        | 27 +++++++++++++++++++
 packaging/deb/alloy.service                   |  2 +-
 packaging/deb/control/postinst                | 10 +++++--
 packaging/environment-file                    |  2 +-
 packaging/rpm/alloy.service                   |  2 +-
 packaging/rpm/control/postinst                | 10 +++++--
 tools/make/packaging.mk                       |  4 +--
 11 files changed, 70 insertions(+), 43 deletions(-)
 delete mode 100644 packaging/alloy.alloy
 create mode 100644 packaging/config.alloy

diff --git a/Dockerfile b/Dockerfile
index 03394dd3f9..68a14a1f3c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -54,6 +54,10 @@ RUN useradd -m -u $UID -g $UID $USERNAME
 RUN chown -R $USERNAME:$USERNAME /etc/alloy
 RUN chown -R $USERNAME:$USERNAME /bin/alloy
 
+RUN mkdir -p /var/lib/alloy/data
+RUN chown -R $USERNAME:$USERNAME /var/lib/alloy
+RUN chmod -R 770 /var/lib/alloy
+
 ENTRYPOINT ["/bin/alloy"]
 ENV ALLOY_DEPLOY_MODE=docker
-CMD ["run", "/etc/alloy/config.alloy", "--storage.path=/etc/alloy/data"]
+CMD ["run", "/etc/alloy/config.alloy", "--storage.path=/var/lib/alloy/data"]
diff --git a/Makefile b/Makefile
index d22cb2de1d..cb93dc4069 100644
--- a/Makefile
+++ b/Makefile
@@ -140,8 +140,12 @@ test:
 	$(GO_ENV) find . -name go.mod -not -path "./go.mod" -execdir go test -race ./... \;
 
 test-packages:
+ifeq ($(USE_CONTAINER),1)
+	$(RERUN_IN_CONTAINER)
+else
 	docker pull $(BUILD_IMAGE)
 	go test -tags=packaging  ./internal/tools/packaging_test
+endif
 
 .PHONY: integration-test
 integration-test:
diff --git a/internal/tools/packaging_test/alloy_linux_packages_test.go b/internal/tools/packaging_test/alloy_linux_packages_test.go
index 824a68ea46..81b59e3332 100644
--- a/internal/tools/packaging_test/alloy_linux_packages_test.go
+++ b/internal/tools/packaging_test/alloy_linux_packages_test.go
@@ -81,9 +81,13 @@ func (env *AlloyEnvironment) TestInstall(t *testing.T) {
 
 	res = env.ExecScript(`[ -f /usr/bin/alloy ]`)
 	require.Equal(t, 0, res.ExitCode, "expected Alloy to be installed")
-	res = env.ExecScript(`[ -f /etc/alloy.alloy ]`)
+	res = env.ExecScript(`[ -f /etc/alloy/config.alloy ]`)
 	require.Equal(t, 0, res.ExitCode, "expected Alloy configuration file to exist")
 
+	res = env.ExecScript(`stat -c '%a:%U:%G' /etc/alloy`)
+	require.Equal(t, "770:root:alloy\n", res.Stdout, "wrong permissions for config folder")
+	require.Equal(t, 0, res.ExitCode, "stat'ing config folder failed")
+
 	res = env.Uninstall()
 	require.Equal(t, 0, res.ExitCode, "uninstalling failed")
 
@@ -94,13 +98,16 @@ func (env *AlloyEnvironment) TestInstall(t *testing.T) {
 }
 
 func (env *AlloyEnvironment) TestConfigPersistence(t *testing.T) {
-	res := env.ExecScript(`echo -n "keepalive" > /etc/alloy.alloy`)
+	res := env.ExecScript(`mkdir -p /etc/alloy`)
+	require.Equal(t, 0, res.ExitCode, "failed to create config directory")
+
+	res = env.ExecScript(`echo -n "keepalive" > /etc/alloy/config.alloy`)
 	require.Equal(t, 0, res.ExitCode, "failed to write config file")
 
 	res = env.Install()
 	require.Equal(t, 0, res.ExitCode, "installation failed")
 
-	res = env.ExecScript(`cat /etc/alloy.alloy`)
+	res = env.ExecScript(`cat /etc/alloy/config.alloy`)
 	require.Equal(t, "keepalive", res.Stdout, "Expected existing file to not be overridden")
 }
 
@@ -110,10 +117,10 @@ func (env *AlloyEnvironment) TestDataFolderPermissions(t *testing.T) {
 	res := env.Install()
 	require.Equal(t, 0, res.ExitCode, "installation failed")
 
-	res = env.ExecScript(`[ -d /var/lib/alloy ]`)
-	require.Equal(t, 0, res.ExitCode, "Expected /var/lib/alloy to have been created during install")
+	res = env.ExecScript(`[ -d /var/lib/alloy/data ]`)
+	require.Equal(t, 0, res.ExitCode, "Expected /var/lib/alloy/data to have been created during install")
 
-	res = env.ExecScript(`stat -c '%a:%U:%G' /var/lib/alloy`)
+	res = env.ExecScript(`stat -c '%a:%U:%G' /var/lib/alloy/data`)
 	require.Equal(t, "770:alloy:alloy\n", res.Stdout, "wrong permissions for data folder")
 	require.Equal(t, 0, res.ExitCode, "stat'ing data folder failed")
 }
diff --git a/packaging/alloy.alloy b/packaging/alloy.alloy
deleted file mode 100644
index 34f6d0abe3..0000000000
--- a/packaging/alloy.alloy
+++ /dev/null
@@ -1,27 +0,0 @@
-// Sample config for Alloy.
-//
-// For a full configuration reference, see https://grafana.com/docs/alloy
-logging {
-	level = "warn"
-}
-
-prometheus.exporter.unix "default" {
-	include_exporter_metrics = true
-	disable_collectors       = ["mdadm"]
-}
-
-prometheus.scrape "default" {
-	targets = concat(
-		prometheus.exporter.unix.default.targets,
-		[{
-			// Self-collect metrics
-			job         = "alloy",
-			__address__ = "127.0.0.1:12345",
-		}],
-	)
-
-	forward_to = [
-	// TODO: components to forward metrics to (like prometheus.remote_write or
-	// prometheus.relabel).
-	]
-}
diff --git a/packaging/config.alloy b/packaging/config.alloy
new file mode 100644
index 0000000000..25963e207e
--- /dev/null
+++ b/packaging/config.alloy
@@ -0,0 +1,27 @@
+// Sample config for Alloy.
+//
+// For a full configuration reference, see https://grafana.com/docs/alloy
+logging {
+  level = "warn"
+}
+
+prometheus.exporter.unix "default" {
+  include_exporter_metrics = true
+  disable_collectors       = ["mdadm"]
+}
+
+prometheus.scrape "default" {
+  targets = concat(
+    prometheus.exporter.unix.default.targets,
+    [{
+      // Self-collect metrics
+      job         = "alloy",
+      __address__ = "127.0.0.1:12345",
+    }],
+  )
+
+  forward_to = [
+  // TODO: components to forward metrics to (like prometheus.remote_write or
+  // prometheus.relabel).
+  ]
+}
diff --git a/packaging/deb/alloy.service b/packaging/deb/alloy.service
index c924dc1308..c722a1bd27 100644
--- a/packaging/deb/alloy.service
+++ b/packaging/deb/alloy.service
@@ -11,7 +11,7 @@ Environment=HOSTNAME=%H
 Environment=ALLOY_DEPLOY_MODE=deb
 EnvironmentFile=/etc/default/alloy
 WorkingDirectory=/var/lib/alloy
-ExecStart=/usr/bin/alloy run $CUSTOM_ARGS --storage.path=/var/lib/alloy $CONFIG_FILE
+ExecStart=/usr/bin/alloy run $CUSTOM_ARGS --storage.path=/var/lib/alloy/data $CONFIG_FILE
 ExecReload=/usr/bin/env kill -HUP $MAINPID
 TimeoutStopSec=20s
 SendSIGKILL=no
diff --git a/packaging/deb/control/postinst b/packaging/deb/control/postinst
index 4042ddf78a..1962060b00 100644
--- a/packaging/deb/control/postinst
+++ b/packaging/deb/control/postinst
@@ -29,8 +29,14 @@ case "$1" in
         chown $ALLOY_USER:$ALLOY_GROUP /var/lib/alloy
         chmod 770 /var/lib/alloy
 
-        chmod 640 /etc/alloy.alloy
-        chown root:$ALLOY_GROUP /etc/alloy.alloy
+        if [ ! -d /var/lib/alloy/data ]; then
+          mkdir /var/lib/alloy/data
+          chown $ALLOY_USER:$ALLOY_GROUP /var/lib/alloy/data
+          chmod 770 /var/lib/alloy/data
+        fi
+
+        chown root:$ALLOY_GROUP /etc/alloy
+        chmod 770 /etc/alloy
 
         if [ -z ${2+x} ] && [ "$RESTART_ON_UPGRADE" = "true" ]; then
             if command -v systemctl 2>/dev/null; then
diff --git a/packaging/environment-file b/packaging/environment-file
index 1aa77bd37b..57a4350b82 100644
--- a/packaging/environment-file
+++ b/packaging/environment-file
@@ -7,7 +7,7 @@
 # Command line options for Alloy.
 #
 # The configuration file holding the Alloy config.
-CONFIG_FILE="/etc/alloy.alloy"
+CONFIG_FILE="/etc/alloy/config.alloy"
 
 # User-defined arguments to pass to the run command.
 CUSTOM_ARGS=""
diff --git a/packaging/rpm/alloy.service b/packaging/rpm/alloy.service
index 192bacd884..7fedb0a5a7 100644
--- a/packaging/rpm/alloy.service
+++ b/packaging/rpm/alloy.service
@@ -11,7 +11,7 @@ Environment=HOSTNAME=%H
 Environment=ALLOY_DEPLOY_MODE=rpm
 EnvironmentFile=/etc/sysconfig/alloy
 WorkingDirectory=/var/lib/alloy
-ExecStart=/usr/bin/alloy run $CUSTOM_ARGS --storage.path=/var/lib/alloy $CONFIG_FILE
+ExecStart=/usr/bin/alloy run $CUSTOM_ARGS --storage.path=/var/lib/alloy/data $CONFIG_FILE
 ExecReload=/usr/bin/env kill -HUP $MAINPID
 TimeoutStopSec=20s
 SendSIGKILL=no
diff --git a/packaging/rpm/control/postinst b/packaging/rpm/control/postinst
index 7a64973254..c02f10a0b6 100644
--- a/packaging/rpm/control/postinst
+++ b/packaging/rpm/control/postinst
@@ -32,8 +32,14 @@ if [ "$1" -eq 1 ] ; then
     chown $ALLOY_USER:$ALLOY_GROUP /var/lib/alloy
     chmod 770 /var/lib/alloy
 
-    chmod 640 /etc/alloy.alloy
-    chown root:$ALLOY_GROUP /etc/alloy.alloy
+    if [ ! -d /var/lib/alloy/data ]; then
+      mkdir /var/lib/alloy/data
+      chown $ALLOY_USER:$ALLOY_GROUP /var/lib/alloy/data
+      chmod 770 /var/lib/alloy/data
+    fi
+
+    chown root:$ALLOY_GROUP /etc/alloy
+    chmod 770 /etc/alloy
 
 elif [ "$1" -ge 2 ] ; then
     add_to_logging_groups
diff --git a/tools/make/packaging.mk b/tools/make/packaging.mk
index 2fcf2625a4..17c77123d6 100644
--- a/tools/make/packaging.mk
+++ b/tools/make/packaging.mk
@@ -124,12 +124,12 @@ define generate_alloy_fpm =
 		-t $(1) \
 		--after-install packaging/$(1)/control/postinst \
 		--before-remove packaging/$(1)/control/prerm \
-		--config-files /etc/alloy.alloy \
+		--config-files /etc/alloy/config.alloy \
 		--config-files $(ALLOY_ENVIRONMENT_FILE_$(1)) \
 		--rpm-rpmbuild-define "_build_id_links none" \
 		--package $(4) \
 			dist/alloy-linux-$(3)=/usr/bin/alloy \
-			packaging/alloy.alloy=/etc/alloy.alloy \
+			packaging/config.alloy=/etc/alloy/config.alloy \
 			packaging/environment-file=$(ALLOY_ENVIRONMENT_FILE_$(1)) \
 			packaging/$(1)/alloy.service=/usr/lib/systemd/system/alloy.service
 endef