aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Audron <me@audron.dev>2026-01-30 18:34:22 +0100
committerMax Audron <me@audron.dev>2026-01-30 18:34:22 +0100
commit34fbe3dd65e37c95019113b8f94f15a4cb0440db (patch)
tree57c5903a18eee88aebe864530ef921de7828560e
parentinit (diff)
add flake
Diffstat (limited to '')
-rw-r--r--.envrc1
-rw-r--r--.gitignore5
-rw-r--r--flake.lock292
-rw-r--r--flake.nix145
-rw-r--r--src/main.rs5
5 files changed, 447 insertions, 1 deletions
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..3550a30
--- /dev/null
+++ b/.envrc
@@ -0,0 +1 @@
+use flake
diff --git a/.gitignore b/.gitignore
index 23362ce..9459c37 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,7 @@
/target
/.serena
+
+# Nix
+result
+result-*
+.direnv
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..954dfec
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,292 @@
+{
+ "nodes": {
+ "crane": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1758758545,
+ "narHash": "sha256-NU5WaEdfwF6i8faJ2Yh+jcK9vVFrofLcwlD/mP65JrI=",
+ "owner": "ipetkov",
+ "repo": "crane",
+ "rev": "95d528a5f54eaba0d12102249ce42f4d01f4e364",
+ "type": "github"
+ },
+ "original": {
+ "owner": "ipetkov",
+ "ref": "v0.21.1",
+ "repo": "crane",
+ "type": "github"
+ }
+ },
+ "dream2nix": {
+ "inputs": {
+ "nixpkgs": [
+ "nci",
+ "nixpkgs"
+ ],
+ "purescript-overlay": "purescript-overlay",
+ "pyproject-nix": "pyproject-nix"
+ },
+ "locked": {
+ "lastModified": 1765953015,
+ "narHash": "sha256-5FBZbbWR1Csp3Y2icfRkxMJw/a/5FGg8hCXej2//bbI=",
+ "owner": "nix-community",
+ "repo": "dream2nix",
+ "rev": "69eb01fa0995e1e90add49d8ca5bcba213b0416f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "dream2nix",
+ "type": "github"
+ }
+ },
+ "flake-compat": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1696426674,
+ "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+ "type": "github"
+ },
+ "original": {
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "type": "github"
+ }
+ },
+ "flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": "nixpkgs-lib"
+ },
+ "locked": {
+ "lastModified": 1768135262,
+ "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "mk-naked-shell": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1681286841,
+ "narHash": "sha256-3XlJrwlR0nBiREnuogoa5i1b4+w/XPe0z8bbrJASw0g=",
+ "owner": "90-008",
+ "repo": "mk-naked-shell",
+ "rev": "7612f828dd6f22b7fb332cc69440e839d7ffe6bd",
+ "type": "github"
+ },
+ "original": {
+ "owner": "90-008",
+ "repo": "mk-naked-shell",
+ "type": "github"
+ }
+ },
+ "nci": {
+ "inputs": {
+ "crane": "crane",
+ "dream2nix": "dream2nix",
+ "mk-naked-shell": "mk-naked-shell",
+ "nixpkgs": [
+ "nixpkgs"
+ ],
+ "parts": "parts",
+ "rust-overlay": "rust-overlay",
+ "treefmt": "treefmt"
+ },
+ "locked": {
+ "lastModified": 1769755038,
+ "narHash": "sha256-4LW7O06gafHpnd2QTU7S8AHcpH7smxX0Egb8bF5dZEc=",
+ "owner": "yusdacra",
+ "repo": "nix-cargo-integration",
+ "rev": "bbd754b60e2f803a4bdd2007387d921262ce6971",
+ "type": "github"
+ },
+ "original": {
+ "owner": "yusdacra",
+ "repo": "nix-cargo-integration",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1769461804,
+ "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs-lib": {
+ "locked": {
+ "lastModified": 1765674936,
+ "narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "nixpkgs.lib",
+ "type": "github"
+ }
+ },
+ "parts": {
+ "inputs": {
+ "nixpkgs-lib": [
+ "nci",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1768135262,
+ "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "purescript-overlay": {
+ "inputs": {
+ "flake-compat": "flake-compat",
+ "nixpkgs": [
+ "nci",
+ "dream2nix",
+ "nixpkgs"
+ ],
+ "slimlock": "slimlock"
+ },
+ "locked": {
+ "lastModified": 1728546539,
+ "narHash": "sha256-Sws7w0tlnjD+Bjck1nv29NjC5DbL6nH5auL9Ex9Iz2A=",
+ "owner": "thomashoneyman",
+ "repo": "purescript-overlay",
+ "rev": "4ad4c15d07bd899d7346b331f377606631eb0ee4",
+ "type": "github"
+ },
+ "original": {
+ "owner": "thomashoneyman",
+ "repo": "purescript-overlay",
+ "type": "github"
+ }
+ },
+ "pyproject-nix": {
+ "inputs": {
+ "nixpkgs": [
+ "nci",
+ "dream2nix",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1763017646,
+ "narHash": "sha256-Z+R2lveIp6Skn1VPH3taQIuMhABg1IizJd8oVdmdHsQ=",
+ "owner": "pyproject-nix",
+ "repo": "pyproject.nix",
+ "rev": "47bd6f296502842643078d66128f7b5e5370790c",
+ "type": "github"
+ },
+ "original": {
+ "owner": "pyproject-nix",
+ "repo": "pyproject.nix",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "flake-parts": "flake-parts",
+ "nci": "nci",
+ "nixpkgs": "nixpkgs"
+ }
+ },
+ "rust-overlay": {
+ "inputs": {
+ "nixpkgs": [
+ "nci",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1769742225,
+ "narHash": "sha256-roSD/OJ3x9nF+Dxr+/bLClX3U8FP9EkCQIFpzxKjSUM=",
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "rev": "bcdd8d37594f0e201639f55889c01c827baf5c75",
+ "type": "github"
+ },
+ "original": {
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "type": "github"
+ }
+ },
+ "slimlock": {
+ "inputs": {
+ "nixpkgs": [
+ "nci",
+ "dream2nix",
+ "purescript-overlay",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1688756706,
+ "narHash": "sha256-xzkkMv3neJJJ89zo3o2ojp7nFeaZc2G0fYwNXNJRFlo=",
+ "owner": "thomashoneyman",
+ "repo": "slimlock",
+ "rev": "cf72723f59e2340d24881fd7bf61cb113b4c407c",
+ "type": "github"
+ },
+ "original": {
+ "owner": "thomashoneyman",
+ "repo": "slimlock",
+ "type": "github"
+ }
+ },
+ "treefmt": {
+ "inputs": {
+ "nixpkgs": [
+ "nci",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1769691507,
+ "narHash": "sha256-8aAYwyVzSSwIhP2glDhw/G0i5+wOrren3v6WmxkVonM=",
+ "owner": "numtide",
+ "repo": "treefmt-nix",
+ "rev": "28b19c5844cc6e2257801d43f2772a4b4c050a1b",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "treefmt-nix",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..32bde23
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,145 @@
+{
+ description = "AC Cup Server - Assetto Corsa Content Update Protocol Server";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+ flake-parts.url = "github:hercules-ci/flake-parts";
+ nci.url = "github:yusdacra/nix-cargo-integration";
+ nci.inputs.nixpkgs.follows = "nixpkgs";
+ };
+
+ outputs = inputs @ { flake-parts, ... }:
+ flake-parts.lib.mkFlake { inherit inputs; } {
+ systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
+
+ imports = [
+ inputs.nci.flakeModule
+ ];
+
+ perSystem = { config, pkgs, system, ... }:
+ let
+ projectName = "ac-cup-server";
+ crateOutputs = config.nci.outputs.${projectName};
+ in
+ {
+ nci.projects.${projectName}.path = ./.;
+ nci.crates.${projectName} = { };
+
+ packages = {
+ default = crateOutputs.packages.release;
+ ac-cup-server = crateOutputs.packages.release;
+ };
+
+ devShells.default = crateOutputs.devShell.overrideAttrs (old: {
+ packages = (old.packages or [ ]) ++ (with pkgs; [
+ rust-analyzer
+ cargo-watch
+ cargo-edit
+ ]);
+ });
+
+ apps.default = {
+ type = "app";
+ program = "${crateOutputs.packages.release}/bin/ac-cup-server";
+ };
+ };
+
+ flake = {
+ nixosModules.default = { config, lib, pkgs, ... }:
+ with lib;
+ let
+ cfg = config.services.ac-cup-server;
+ in
+ {
+ options.services.ac-cup-server = {
+ enable = mkEnableOption "AC Cup Server";
+
+ package = mkOption {
+ type = types.package;
+ default = inputs.self.packages.${pkgs.system}.default;
+ defaultText = literalExpression "inputs.self.packages.\${pkgs.system}.default";
+ description = "The ac-cup-server package to use.";
+ };
+
+ host = mkOption {
+ type = types.str;
+ default = "0.0.0.0";
+ example = "127.0.0.1";
+ description = "IP address to bind to.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 3000;
+ description = "Port to listen on.";
+ };
+
+ storagePath = mkOption {
+ type = types.str;
+ default = "/var/lib/ac-cup-server/storage.json";
+ description = "Path to the storage JSON file.";
+ };
+
+ environmentFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = "Environment file to load additional configuration from.";
+ };
+
+ logLevel = mkOption {
+ type = types.str;
+ default = "info";
+ example = "debug";
+ description = "Log level for the service (trace, debug, info, warn, error).";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.ac-cup-server = {
+ description = "AC Cup Server";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+
+ serviceConfig = {
+ Type = "simple";
+ DynamicUser = true;
+ StateDirectory = "ac-cup-server";
+ ExecStart = "${cfg.package}/bin/ac-cup-server";
+ Restart = "on-failure";
+ RestartSec = "5s";
+
+ # Hardening
+ NoNewPrivileges = true;
+ PrivateTmp = true;
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ PrivateDevices = true;
+ ProtectClock = true;
+ };
+
+ environment = {
+ HOST = cfg.host;
+ PORT = toString cfg.port;
+ STORAGE_PATH = cfg.storagePath;
+ RUST_LOG = "ac_cup_server=${cfg.logLevel},tower_http=${cfg.logLevel},axum=${cfg.logLevel}";
+ };
+
+ inherit (cfg) environmentFile;
+ };
+ };
+ };
+ };
+ };
+}
+
+
+
+
diff --git a/src/main.rs b/src/main.rs
index e49cada..b45132c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -48,12 +48,15 @@ async fn main() {
.layer(TraceLayer::new_for_http())
.with_state(shared_storage);
+ let host = env::var("HOST")
+ .unwrap_or_else(|_| "0.0.0.0".to_string());
+
let port = env::var("PORT")
.unwrap_or_else(|_| "3000".to_string())
.parse::<u16>()
.expect("PORT must be a valid number");
- let addr = format!("0.0.0.0:{}", port);
+ let addr = format!("{}:{}", host, port);
let listener = tokio::net::TcpListener::bind(&addr)
.await
.expect("Failed to bind to address");