From: Dan Fuhry Date: Sat, 14 Mar 2026 23:30:58 +0000 (-0400) Subject: [cmd/*] use generated systemd services X-Git-Url: https://go.fuhry.dev/?a=commitdiff_plain;h=b6e0f35d88e7db627b4760bf766f5744cd2fb251;p=runtime.git [cmd/*] use generated systemd services Part 1/?? of packaging/distribution overhaul: generate systemd services with bazel rules adjacent to cmd `go_binary` targets. --- diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel new file mode 100644 index 0000000..7c43789 --- /dev/null +++ b/bazel/BUILD.bazel @@ -0,0 +1,4 @@ +exports_files([ + "systemd.service.in", + "systemd-dbus.service.in", +]) diff --git a/bazel/subst.bzl b/bazel/subst.bzl new file mode 100644 index 0000000..abe5505 --- /dev/null +++ b/bazel/subst.bzl @@ -0,0 +1,54 @@ +def stamp_subst( + name, + srcs, + outs, + additional_vars = {}, +): + additional_vars_str = "" + for k, v in additional_vars.items(): + additional_vars_str += '{} {}'.format(k, v) + + native.genrule( + name = name, + srcs = srcs, + outs = outs, + cmd_bash = """ + sedexp=() + while read line; do + varname="$$(cut -d\\ -f1 <<< "$$line")" + len=$$(( $${#varname} + 1 )) + varval="$${line:$$len}" + sedexp+=("-e" 's;\\$$'"$$varname;$$varval;g") + done < <(cat bazel-out/volatile-status.txt; cat <<'EOF' +"""+additional_vars_str+""" +EOF +) + sed -r "$${sedexp[@]}" < "$<" > "$@" + """, + stamp = 1, + ) + + +def subst( + name, # type: str + src, # type: str + out, # type: str + additional_vars = {}, # type: dict[str, str] + visibility = [], +): + args = [] + for k, v in additional_vars.items(): + args.append("'--var={}={}'".format(k, v.replace("'", "'\\''"))) + + native.genrule( + name = name, + srcs = [src], + outs = [out], + cmd = """ + ./$(location //bazel/subst:subst) {} < "$<" > "$@" + """.format(' '.join(args)), + tools = [ + "//bazel/subst:subst" + ], + visibility = visibility, + ) \ No newline at end of file diff --git a/bazel/svc.bzl b/bazel/svc.bzl new file mode 100644 index 0000000..4ee239c --- /dev/null +++ b/bazel/svc.bzl @@ -0,0 +1,81 @@ +load("//bazel:subst.bzl", "subst") + +def systemd_service( + name, + exe, + args = [], + description = "runtime service with no description provided", + deps = ["network-online.target"], + user = "nobody", + group = "nobody", + type = "simple", + environment_file = None, + visibility = ["//visibility:public"], +): + installed_exe_name = exe.replace("_", "-") + environment_file = environment_file or ( + '${const:ExePrefix}'+installed_exe_name+'@%i' + if '@' in name + else '${const:ExePrefix}'+installed_exe_name + ) + exvars = { + "WANTS": " ".join(deps).replace('$', '$$'), + "AFTER": " ".join(deps).replace('$', '$$'), + "DESCRIPTION": description.replace('$', '$$'), + "EXE": installed_exe_name, + "ENV_FILE": environment_file.replace('$', '$$'), + "USER": user, + "GROUP": group, + "ARGS": " ".join(args).replace('$', '$$'), + "TYPE": type, + } + + subst( + name = name.replace("-", "_") + "_systemd_service", + src = "//bazel:systemd.service.in", + out = name + ".service", + additional_vars = exvars, + visibility = visibility, + ) + + +def systemd_dbus_service( + name, + exe, + bus_name, + args = [], + description = "runtime service with no description provided", + deps = ["network-online.target"], + user = "nobody", + group = "nobody", + type = "simple", + environment_file = None, + visibility = ["//visibility:public"], +): + installed_exe_name = exe.replace("_", "-") + environment_file = environment_file or ( + '{}@%i'.format(installed_exe_name) if '@' in name else installed_exe_name + ) + exvars = { + "WANTS": " ".join(deps).replace('$', '$$'), + "AFTER": " ".join(deps).replace('$', '$$'), + "DESCRIPTION": description.replace('$', '$$'), + "EXE": installed_exe_name, + "ENV_FILE": environment_file.replace('$', '$$'), + "BUS_NAME": bus_name, + "USER": user, + "GROUP": group, + "ARGS": " ".join(args).replace('$', '$$'), + "TYPE": type, + } + + subst( + name = name.replace("-", "_") + "_systemd_service", + src = "//bazel:systemd-dbus.service.in", + out = name + ".service", + additional_vars = exvars, + visibility = visibility, + ) + + + diff --git a/bazel/systemd-dbus.service.in b/bazel/systemd-dbus.service.in new file mode 100644 index 0000000..18947f7 --- /dev/null +++ b/bazel/systemd-dbus.service.in @@ -0,0 +1,15 @@ +[Unit] +Description=${DESCRIPTION} +Wants=${WANTS:-network-online.target} +After=${AFTER:-network-online.target} + +[Service] +Type=dbus +BusName=${const:DbusPrefix}.${BUS_NAME}.v1 +User=${USER:-nobody} +Group=${GROUP:-${USER:-nobody}} +ExecStart=${EXEDIR:-/usr/bin}/${const:EXE_PREFIX}${EXE} ${ARGS:-} + +[Install] +Alias=${const:DbusPrefix}.${BUS_NAME}.service +WantedBy=multi-user.target diff --git a/bazel/systemd.service.in b/bazel/systemd.service.in new file mode 100644 index 0000000..bcfabff --- /dev/null +++ b/bazel/systemd.service.in @@ -0,0 +1,15 @@ +[Unit] +Description=${DESCRIPTION} +Wants=${WANTS:-network-online.target} +After=${AFTER:-network-online.target} + +[Service] +Type=${TYPE} +User=${USER:-nobody} +Group=${GROUP:-${USER:-nobody}} +EnvironmentFile=-/etc/conf.d/${ENV_FILE:-${const:ExePrefix}${EXE}} +ExecStart=${EXEDIR:-/usr/bin}/${const:ExePrefix}${EXE} ${ARGS:-} + +[Install] +WantedBy=multi-user.target + diff --git a/bazel/workspace-status b/bazel/workspace-status index 911a78e..44a1f99 100755 --- a/bazel/workspace-status +++ b/bazel/workspace-status @@ -17,6 +17,7 @@ DBUS_PREFIX="${DBUS_PREFIX:-"dev.fuhry.runtime"}" DBUS_PATH="${DBUS_PATH:-"/${DBUS_PREFIX//\./\/}"}" ORG_NAME="${ORG_NAME:-"FooCorp"}" ORG_SLUG="${ORG_SLUG:-"runtime"}" +EXE_PREFIX="${EXE_PREFIX:-}" SYSTEM_CONF_DIR="${SYSTEM_CONF_DIR:-"/etc/${ORG_SLUG}"}" ROOT_CA_NAME="${ROOT_CA_NAME:-"${ORG_NAME} Root"}" INT_CA_NAME="${INT_CA_NAME:-"${ORG_NAME} Intermediate mTLS"}" @@ -38,6 +39,7 @@ vars=( DBUS_PATH ORG_NAME ORG_SLUG + EXE_PREFIX SYSTEM_CONF_DIR ROOT_CA_NAME INT_CA_NAME diff --git a/cmd/apcups_exporter/BUILD.bazel b/cmd/apcups_exporter/BUILD.bazel index 5357380..6d7512f 100644 --- a/cmd/apcups_exporter/BUILD.bazel +++ b/cmd/apcups_exporter/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_service") go_library( name = "apcups_exporter_lib", @@ -19,3 +20,28 @@ go_binary( embed = [":apcups_exporter_lib"], visibility = ["//visibility:public"], ) + +systemd_service( + name = "apcupsd-exporter", + description = "apcupsd-exporter polls APC uninterruptible power supplies (UPSes) via apcupsd and exports metrics via metric-collector", + exe = "apcups_exporter", + group = "daemon", + type = "notify", + user = "daemon", + deps = ["apcupsd.service"], +) + +systemd_service( + name = "apcupsd-exporter@", + args = [ + "--metricbus.client.service-discriminator=%i", + "$APCUPSD_EXPORTER_ARGS", + ], + description = "apcupsd-exporter polls apcupsd for UPS %i and exports metrics via metric-collector", + environment_file = "$${const:ExePrefix}apcupsd-exporter@%i", + exe = "apcups_exporter", + group = "daemon", + type = "notify", + user = "daemon", + deps = ["apcupsd.service"], +) diff --git a/cmd/apcups_exporter/systemd/apcupsd-exporter.service b/cmd/apcups_exporter/systemd/apcupsd-exporter.service deleted file mode 100644 index b815ead..0000000 --- a/cmd/apcups_exporter/systemd/apcupsd-exporter.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Export stats from apcupsd via metric-collector -Requires=apcupsd.service - -[Service] -Type=notify -User=daemon -ExecStart=/usr/bin/apcupsd-exporter - -[Install] -WantedBy=default.target diff --git a/cmd/http_proxy/BUILD.bazel b/cmd/http_proxy/BUILD.bazel index edf922b..e701030 100644 --- a/cmd/http_proxy/BUILD.bazel +++ b/cmd/http_proxy/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_service") go_library( name = "http_proxy_lib", @@ -21,3 +22,15 @@ go_binary( embed = [":http_proxy_lib"], visibility = ["//visibility:public"], ) + +systemd_service( + name = "http-proxy@", + args = [ + "--config=${const:SystemConfDir}/proxy/%i.yaml", + ], + description = "http-proxy instance %i", + exe = "http_proxy", + group = "http", + type = "notify", + user = "http", +) diff --git a/cmd/http_proxy/systemd/http-proxy@.service b/cmd/http_proxy/systemd/http-proxy@.service deleted file mode 100644 index 9175d0b..0000000 --- a/cmd/http_proxy/systemd/http-proxy@.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Proxy instance %i - -[Service] -Type=notify -User=http -ExecStart=/usr/bin/proxy -config=/etc/runtime/proxy/%i.yaml - -[Install] -WantedBy=default.target diff --git a/cmd/ldap_health_exporter/BUILD.bazel b/cmd/ldap_health_exporter/BUILD.bazel index ed82caa..472fe00 100644 --- a/cmd/ldap_health_exporter/BUILD.bazel +++ b/cmd/ldap_health_exporter/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_service") go_library( name = "ldap_health_exporter_lib", @@ -20,3 +21,16 @@ go_binary( embed = [":ldap_health_exporter_lib"], visibility = ["//visibility:public"], ) + +systemd_service( + name = "ldap-health-exporter@", + args = [ + "--webCfgFile=/etc/prometheus-node-exporter/web-config.yml", + "--ldapAddr=%i:636", + "--mtlsId=slapmon", + "--interval=30s", + ], + description = "Monitor LDAP server health on %i", + exe = "ldap_health_exporter", + user = "slapmon", +) diff --git a/cmd/metricbus_server/BUILD.bazel b/cmd/metricbus_server/BUILD.bazel index 46abb28..dceea28 100644 --- a/cmd/metricbus_server/BUILD.bazel +++ b/cmd/metricbus_server/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_dbus_service") go_library( name = "metricbus_server_lib", @@ -17,3 +18,15 @@ go_binary( embed = [":metricbus_server_lib"], visibility = ["//visibility:public"], ) + +systemd_dbus_service( + name = "metric-collector", + args = [ + "--mtls.id=node-exporter", + ], + bus_name = "metrics.MetricCollector", + description = "metricbus-server collects metrics from other services via dbus and exports them via a single OpenTelemetry endpoint", + exe = "metricbus_server", + group = "node_exporter", + user = "node_exporter", +) diff --git a/cmd/mtls_exporter/BUILD.bazel b/cmd/mtls_exporter/BUILD.bazel index 24d2978..1e59ec1 100644 --- a/cmd/mtls_exporter/BUILD.bazel +++ b/cmd/mtls_exporter/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_service") go_library( name = "mtls_exporter_lib", @@ -17,3 +18,15 @@ go_binary( embed = [":mtls_exporter_lib"], visibility = ["//visibility:public"], ) + +systemd_service( + name = "mtls-exporter", + description = "mtls-exporter exports metrics for health and remaining lifetime of mTLS certificates", + exe = "mtls_exporter", + group = "root", + type = "notify", + user = "root", + deps = [ + "${const:ExePrefix}metric-collector.service", + ], +) diff --git a/cmd/mtls_exporter/systemd/mtls-exporter.service b/cmd/mtls_exporter/systemd/mtls-exporter.service deleted file mode 100644 index f6939ac..0000000 --- a/cmd/mtls_exporter/systemd/mtls-exporter.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Export mTLS certificate status -Requires=metric-collector.service - -[Service] -Type=notify -User=root -ExecStart=/usr/bin/mtls-exporter - -[Install] -WantedBy=default.target diff --git a/cmd/prometheus_http_discovery/BUILD.bazel b/cmd/prometheus_http_discovery/BUILD.bazel index a35c126..b98bc6d 100644 --- a/cmd/prometheus_http_discovery/BUILD.bazel +++ b/cmd/prometheus_http_discovery/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_service") go_library( name = "prometheus_http_discovery_lib", @@ -20,3 +21,10 @@ go_binary( embed = [":prometheus_http_discovery_lib"], visibility = ["//visibility:public"], ) + +systemd_service( + name = "prometheus-http-discovery", + description = "Prometheus HTTP endpoint discoverer monitors service discovery entries and returns Prometheus http_sd_config JSON", + exe = "prometheus_http_discovery", + type = "notify", +) diff --git a/cmd/prometheus_http_discovery/systemd/prometheus-http-discovery.service b/cmd/prometheus_http_discovery/systemd/prometheus-http-discovery.service deleted file mode 100644 index 9b63216..0000000 --- a/cmd/prometheus_http_discovery/systemd/prometheus-http-discovery.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Prometheus HTTP endpoint discoverer monitors service discovery entries and returns Prometheus http_sd_config JSON - -[Service] -Type=notify -User=nobody -ExecStart=/usr/bin/prometheus-http-discovery - -[Install] -WantedBy=default.target diff --git a/cmd/sd_health_exporter/BUILD.bazel b/cmd/sd_health_exporter/BUILD.bazel index 7030a73..da61a04 100644 --- a/cmd/sd_health_exporter/BUILD.bazel +++ b/cmd/sd_health_exporter/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_service") go_library( name = "sd_health_exporter_lib", @@ -18,3 +19,14 @@ go_binary( embed = [":sd_health_exporter_lib"], visibility = ["//visibility:public"], ) + +systemd_service( + name = "sd-health-exporter", + args = [ + "--mtls.id=node-exporter", + ], + description = "sd-health-exporter exports Prometheus metrics for service health", + exe = "sd_health_exporter", + group = "node_exporter", + user = "node_exporter", +) diff --git a/cmd/sd_register/BUILD.bazel b/cmd/sd_register/BUILD.bazel index 63e4a58..1ac2f6b 100644 --- a/cmd/sd_register/BUILD.bazel +++ b/cmd/sd_register/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_go//go:def.bzl", "go_binary", "go_library") +load("//bazel:svc.bzl", "systemd_service") go_library( name = "sd_register_lib", @@ -19,3 +20,27 @@ go_binary( embed = [":sd_register_lib"], visibility = ["//visibility:public"], ) + +systemd_service( + name = "sd-register", + args = [ + "--service=${const:SystemConfDir}/sd", + ], + description = "sd-register registers services in service discovery and continually renews them based on health-checks", + exe = "sd-register", + group = "$${const:OrgSlug}", + user = "$${const:OrgSlug}", +) + +systemd_service( + name = "sd-register@", + args = [ + "--mtls.id=etcd-client", + "--service=${const:SystemConfDir}/sd/%i", + "--domain=%i", + ], + description = "sd-register registers services for the domain %i in service discovery and continually renews them based on health-checks", + exe = "sd-register", + group = "$${const:OrgSlug}", + user = "$${const:OrgSlug}", +) diff --git a/http/proxy/systemd/http-proxy@.service b/http/proxy/systemd/http-proxy@.service deleted file mode 100644 index 9175d0b..0000000 --- a/http/proxy/systemd/http-proxy@.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Proxy instance %i - -[Service] -Type=notify -User=http -ExecStart=/usr/bin/proxy -config=/etc/runtime/proxy/%i.yaml - -[Install] -WantedBy=default.target diff --git a/metrics/metricbus/systemd/metric-collector.service b/metrics/metricbus/systemd/metric-collector.service deleted file mode 100644 index caff109..0000000 --- a/metrics/metricbus/systemd/metric-collector.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Metric Collector - -[Service] -Type=dbus -User=node_exporter -BusName=dev.fuhry.runtime.metrics.MetricCollector.v1 -ExecStart=/usr/bin/metricbus-collector -mtls.id=node-exporter - -[Install] -Alias=dev.fuhry.runtime.metrics.MetricCollector.service -WantedBy=default.target diff --git a/sd/systemd/sd-health-exporter.service b/sd/systemd/sd-health-exporter.service deleted file mode 100644 index 408b0b7..0000000 --- a/sd/systemd/sd-health-exporter.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Export Prometheus metrics for service health -Wants=systemd-networkd-wait-online.service -After=systemd-networkd-wait-online.service - -[Service] -Type=simple -User=node_exporter -Group=node_exporter -Environment=MTLS_IDENTITY=node-exporter -ExecStart=/usr/bin/health-exporter -mtls.id=${MTLS_IDENTITY} - -[Install] -WantedBy=multi-user.target diff --git a/sd/systemd/sd-register.service b/sd/systemd/sd-register.service deleted file mode 100644 index afb56dc..0000000 --- a/sd/systemd/sd-register.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Service discovery and health checking for %i -Wants=network-online.target -After=network-online.target - -[Service] -Type=simple -User=nobody -Group=nobody -ExecStart=/usr/bin/sd-register -service /etc/runtime/sd - -[Install] -WantedBy=multi-user.target - diff --git a/sd/systemd/sd-register@.service b/sd/systemd/sd-register@.service deleted file mode 100644 index fa87160..0000000 --- a/sd/systemd/sd-register@.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Service discovery and health checking for %i -Wants=network-online.target -After=network-online.target - -[Service] -Type=simple -User=nobody -Group=nobody -ExecStart=/usr/bin/sd-register -mtls.id=etcd-client -service /etc/runtime/sd/%i -domain %i - -[Install] -WantedBy=multi-user.target -