Rename project from system-stats-daemon to systant
- Updated all module names from SystemStatsDaemon to Systant - Renamed application config from :system_stats_daemon to :systant - Updated service files and documentation - Release binary now at _build/prod/rel/systant/bin/systant 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9d8306a64b
commit
92fc90e3b4
16
README.md
16
README.md
@ -1,4 +1,4 @@
|
|||||||
# System Stats Daemon
|
# Systant
|
||||||
|
|
||||||
An Elixir application that runs as a systemd daemon to:
|
An Elixir application that runs as a systemd daemon to:
|
||||||
1. Publish system stats to MQTT every 30 seconds
|
1. Publish system stats to MQTT every 30 seconds
|
||||||
@ -9,10 +9,10 @@ An Elixir application that runs as a systemd daemon to:
|
|||||||
Edit `config/config.exs` to configure MQTT connection:
|
Edit `config/config.exs` to configure MQTT connection:
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
config :system_stats_daemon, SystemStatsDaemon.MqttClient,
|
config :systant, Systant.MqttClient,
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
port: 1883,
|
port: 1883,
|
||||||
client_id: "system_stats_daemon",
|
client_id: "systant",
|
||||||
username: nil,
|
username: nil,
|
||||||
password: nil,
|
password: nil,
|
||||||
stats_topic: "system/stats",
|
stats_topic: "system/stats",
|
||||||
@ -35,24 +35,24 @@ mix run --no-halt
|
|||||||
|
|
||||||
# Production release
|
# Production release
|
||||||
MIX_ENV=prod mix release
|
MIX_ENV=prod mix release
|
||||||
_build/prod/rel/system_stats_daemon/bin/system_stats_daemon start
|
_build/prod/rel/systant/bin/systant start
|
||||||
```
|
```
|
||||||
|
|
||||||
## Systemd Installation
|
## Systemd Installation
|
||||||
|
|
||||||
1. Build production release
|
1. Build production release
|
||||||
2. Copy binary to `/usr/local/bin/`
|
2. Copy binary to `/usr/local/bin/`
|
||||||
3. Copy `system_stats_daemon.service` to `/etc/systemd/system/`
|
3. Copy `systant.service` to `/etc/systemd/system/`
|
||||||
4. Enable and start:
|
4. Enable and start:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo systemctl enable system_stats_daemon
|
sudo systemctl enable systant
|
||||||
sudo systemctl start system_stats_daemon
|
sudo systemctl start systant
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Publishes "Hello world" stats every 30 seconds to `system/stats` topic
|
- Publishes "Hello from systant" stats every 30 seconds to `system/stats` topic
|
||||||
- Listens on `system/commands` topic and logs received messages
|
- Listens on `system/commands` topic and logs received messages
|
||||||
- Configurable MQTT connection settings
|
- Configurable MQTT connection settings
|
||||||
- Runs as systemd daemon with auto-restart
|
- Runs as systemd daemon with auto-restart
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import Config
|
import Config
|
||||||
|
|
||||||
config :system_stats_daemon, SystemStatsDaemon.MqttClient,
|
config :systant, Systant.MqttClient,
|
||||||
host: "mqtt.home",
|
host: "mqtt.home",
|
||||||
port: 1883,
|
port: 1883,
|
||||||
client_id: "system_stats_daemon",
|
client_id: "systant",
|
||||||
username: "mqtt",
|
username: "mqtt",
|
||||||
password: "pleasework",
|
password: "pleasework",
|
||||||
stats_topic: "system/stats",
|
stats_topic: "system/stats",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
defmodule SystemStatsDaemon do
|
defmodule Systant do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Documentation for `SystemStatsDaemon`.
|
Documentation for `Systant`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
@ -8,7 +8,7 @@ defmodule SystemStatsDaemon do
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> SystemStatsDaemon.hello()
|
iex> Systant.hello()
|
||||||
:world
|
:world
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -1,4 +1,4 @@
|
|||||||
defmodule SystemStatsDaemon.Application do
|
defmodule Systant.Application do
|
||||||
# See https://hexdocs.pm/elixir/Application.html
|
# See https://hexdocs.pm/elixir/Application.html
|
||||||
# for more information on OTP Applications
|
# for more information on OTP Applications
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
@ -8,12 +8,12 @@ defmodule SystemStatsDaemon.Application do
|
|||||||
@impl true
|
@impl true
|
||||||
def start(_type, _args) do
|
def start(_type, _args) do
|
||||||
children = [
|
children = [
|
||||||
{SystemStatsDaemon.MqttClient, []}
|
{Systant.MqttClient, []}
|
||||||
]
|
]
|
||||||
|
|
||||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||||
# for other strategies and supported options
|
# for other strategies and supported options
|
||||||
opts = [strategy: :one_for_one, name: SystemStatsDaemon.Supervisor]
|
opts = [strategy: :one_for_one, name: Systant.Supervisor]
|
||||||
Supervisor.start_link(children, opts)
|
Supervisor.start_link(children, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1,4 +1,4 @@
|
|||||||
defmodule SystemStatsDaemon.MqttClient do
|
defmodule Systant.MqttClient do
|
||||||
use GenServer
|
use GenServer
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ defmodule SystemStatsDaemon.MqttClient do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def init(_opts) do
|
def init(_opts) do
|
||||||
config = Application.get_env(:system_stats_daemon, __MODULE__)
|
config = Application.get_env(:systant, __MODULE__)
|
||||||
Logger.info("Starting MQTT client with config: #{inspect(config)}")
|
Logger.info("Starting MQTT client with config: #{inspect(config)}")
|
||||||
|
|
||||||
# Use a unique client ID to avoid conflicts
|
# Use a unique client ID to avoid conflicts
|
||||||
@ -32,7 +32,7 @@ defmodule SystemStatsDaemon.MqttClient do
|
|||||||
|
|
||||||
# Send immediate hello message
|
# Send immediate hello message
|
||||||
hello_msg = %{
|
hello_msg = %{
|
||||||
message: "Hello - system_stats_daemon started",
|
message: "Hello - systant started",
|
||||||
timestamp: DateTime.utc_now() |> DateTime.to_iso8601(),
|
timestamp: DateTime.utc_now() |> DateTime.to_iso8601(),
|
||||||
hostname: get_hostname()
|
hostname: get_hostname()
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ defmodule SystemStatsDaemon.MqttClient do
|
|||||||
|
|
||||||
defp publish_stats(config, client_id) do
|
defp publish_stats(config, client_id) do
|
||||||
stats = %{
|
stats = %{
|
||||||
message: "Hello from system_stats_daemon",
|
message: "Hello from systant",
|
||||||
timestamp: DateTime.utc_now() |> DateTime.to_iso8601(),
|
timestamp: DateTime.utc_now() |> DateTime.to_iso8601(),
|
||||||
hostname: get_hostname()
|
hostname: get_hostname()
|
||||||
}
|
}
|
||||||
6
mix.exs
6
mix.exs
@ -3,7 +3,7 @@ defmodule SystemStatsDaemon.MixProject do
|
|||||||
|
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :system_stats_daemon,
|
app: :systant,
|
||||||
version: "0.1.0",
|
version: "0.1.0",
|
||||||
elixir: "~> 1.18",
|
elixir: "~> 1.18",
|
||||||
start_permanent: Mix.env() == :prod,
|
start_permanent: Mix.env() == :prod,
|
||||||
@ -16,7 +16,7 @@ defmodule SystemStatsDaemon.MixProject do
|
|||||||
def application do
|
def application do
|
||||||
[
|
[
|
||||||
extra_applications: [:logger],
|
extra_applications: [:logger],
|
||||||
mod: {SystemStatsDaemon.Application, []}
|
mod: {Systant.Application, []}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ defmodule SystemStatsDaemon.MixProject do
|
|||||||
|
|
||||||
defp releases do
|
defp releases do
|
||||||
[
|
[
|
||||||
system_stats_daemon: [
|
systant: [
|
||||||
include_executables_for: [:unix],
|
include_executables_for: [:unix],
|
||||||
applications: [runtime_tools: :permanent]
|
applications: [runtime_tools: :permanent]
|
||||||
]
|
]
|
||||||
|
|||||||
@ -3,15 +3,15 @@
|
|||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.system-stats-daemon;
|
cfg = config.services.systant;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.system-stats-daemon = {
|
options.services.systant = {
|
||||||
enable = mkEnableOption "System Stats MQTT Daemon";
|
enable = mkEnableOption "Systant MQTT Daemon";
|
||||||
|
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
description = "The system-stats-daemon package to use";
|
description = "The systant package to use";
|
||||||
};
|
};
|
||||||
|
|
||||||
mqttHost = mkOption {
|
mqttHost = mkOption {
|
||||||
@ -58,8 +58,8 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
systemd.services.system-stats-daemon = {
|
systemd.services.systant = {
|
||||||
description = "System Stats MQTT Daemon";
|
description = "Systant MQTT Daemon";
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
@ -77,13 +77,13 @@ in
|
|||||||
Type = "exec";
|
Type = "exec";
|
||||||
User = "root";
|
User = "root";
|
||||||
Group = "root";
|
Group = "root";
|
||||||
ExecStart = "${cfg.package}/bin/system_stats_daemon start";
|
ExecStart = "${cfg.package}/bin/systant start";
|
||||||
ExecStop = "${cfg.package}/bin/system_stats_daemon stop";
|
ExecStop = "${cfg.package}/bin/systant stop";
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
RestartSec = 5;
|
RestartSec = 5;
|
||||||
StandardOutput = "journal";
|
StandardOutput = "journal";
|
||||||
StandardError = "journal";
|
StandardError = "journal";
|
||||||
SyslogIdentifier = "system_stats_daemon";
|
SyslogIdentifier = "systant";
|
||||||
WorkingDirectory = "${cfg.package}";
|
WorkingDirectory = "${cfg.package}";
|
||||||
|
|
||||||
# Security settings
|
# Security settings
|
||||||
|
|||||||
59
systant.nix
Normal file
59
systant.nix
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
{ lib
|
||||||
|
, stdenv
|
||||||
|
, fetchgit
|
||||||
|
, elixir
|
||||||
|
, erlang
|
||||||
|
, rebar3
|
||||||
|
, git
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "systant";
|
||||||
|
version = "0.1.0";
|
||||||
|
|
||||||
|
src = fetchgit {
|
||||||
|
url = "https://git.ryanpandya.com/ryan/systant.git";
|
||||||
|
rev = "9d8306a64b7893ea0d25e2b08f470541fb4db7c8";
|
||||||
|
sha256 = lib.fakeSha256; # Replace with actual hash after first build attempt
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
elixir
|
||||||
|
erlang
|
||||||
|
rebar3
|
||||||
|
git
|
||||||
|
];
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
export MIX_ENV=prod
|
||||||
|
export MIX_HOME=$TMPDIR/mix
|
||||||
|
export HEX_HOME=$TMPDIR/hex
|
||||||
|
export REBAR_CACHE_DIR=$TMPDIR/rebar3
|
||||||
|
|
||||||
|
mix local.hex --force
|
||||||
|
mix local.rebar --force
|
||||||
|
mix deps.get --only=prod
|
||||||
|
mix release
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r _build/prod/rel/systant/* $out/
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Systant - System stats MQTT daemon for monitoring system metrics";
|
||||||
|
homepage = "https://git.ryanpandya.com/ryan/systant";
|
||||||
|
license = licenses.mit; # Update if different
|
||||||
|
maintainers = [ ]; # Add your maintainer info if desired
|
||||||
|
platforms = platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,19 +1,19 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=System Stats MQTT Daemon
|
Description=Systant MQTT Daemon
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=exec
|
Type=exec
|
||||||
User=root
|
User=root
|
||||||
Group=root
|
Group=root
|
||||||
ExecStart=/opt/system_stats_daemon/bin/system_stats_daemon start
|
ExecStart=/opt/systant/bin/systant start
|
||||||
ExecStop=/opt/system_stats_daemon/bin/system_stats_daemon stop
|
ExecStop=/opt/systant/bin/systant stop
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
StandardOutput=journal
|
StandardOutput=journal
|
||||||
StandardError=journal
|
StandardError=journal
|
||||||
SyslogIdentifier=system_stats_daemon
|
SyslogIdentifier=systant
|
||||||
WorkingDirectory=/opt/system_stats_daemon
|
WorkingDirectory=/opt/systant
|
||||||
|
|
||||||
# Security settings - still apply restrictions where possible
|
# Security settings - still apply restrictions where possible
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
8
test/systant_test.exs
Normal file
8
test/systant_test.exs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
defmodule SystantTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
doctest Systant
|
||||||
|
|
||||||
|
test "greets the world" do
|
||||||
|
assert Systant.hello() == :world
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,8 +0,0 @@
|
|||||||
defmodule SystemStatsDaemonTest do
|
|
||||||
use ExUnit.Case
|
|
||||||
doctest SystemStatsDaemon
|
|
||||||
|
|
||||||
test "greets the world" do
|
|
||||||
assert SystemStatsDaemon.hello() == :world
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Loading…
Reference in New Issue
Block a user