first commit
This commit is contained in:
47
README.md
Normal file
47
README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# wafrn-nix
|
||||
|
||||
example:
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs.wafrn-nix.url = "git+https://git.ocbwoy3.dev/kris/wafrn-nix";
|
||||
|
||||
outputs = { self, nixpkgs, wafrn-nix, ... }: {
|
||||
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
wafrn-nix.nixosModules.default
|
||||
({ ... }: {
|
||||
virtualisation.docker.enable = true;
|
||||
|
||||
services.wafrn = {
|
||||
enable = true;
|
||||
source = "/srv/wafrn";
|
||||
stateDir = "/var/lib/wafrn";
|
||||
secretsFile = "/run/secrets/wafrn.env";
|
||||
|
||||
# cloudflared doesnt need https:
|
||||
# httpPort = 8080;
|
||||
# httpsPort = null;
|
||||
|
||||
bun2nix = {
|
||||
enable = true;
|
||||
outputFile = "bun.nix";
|
||||
};
|
||||
|
||||
environment = {
|
||||
DOMAIN_NAME = "wafrn.example.com";
|
||||
CACHE_DOMAIN = "cache.wafrn.example.com";
|
||||
MEDIA_DOMAIN = "media.wafrn.example.com";
|
||||
FRONTEND_MEDIA_URL = "https://media.wafrn.example.com";
|
||||
FRONTEND_CACHE_URL = "https://cache.wafrn.example.com/api/cache?media=";
|
||||
FRONTEND_FQDN_URL = "https://wafrn.example.com";
|
||||
ACME_EMAIL = "admin@example.com";
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
136
flake.lock
generated
Normal file
136
flake.lock
generated
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"nodes": {
|
||||
"bun2nix": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"import-tree": "import-tree",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1770895533,
|
||||
"narHash": "sha256-v3QaK9ugy9bN9RXDnjw0i2OifKmz2NnKM82agtqm/UY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "bun2nix",
|
||||
"rev": "c843f477b15f51151f8c6bcc886954699440a6e1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "bun2nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769996383,
|
||||
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"import-tree": {
|
||||
"locked": {
|
||||
"lastModified": 1763762820,
|
||||
"narHash": "sha256-ZvYKbFib3AEwiNMLsejb/CWs/OL/srFQ8AogkebEPF0=",
|
||||
"owner": "vic",
|
||||
"repo": "import-tree",
|
||||
"rev": "3c23749d8013ec6daa1d7255057590e9ca726646",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "vic",
|
||||
"repo": "import-tree",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1771419570,
|
||||
"narHash": "sha256-bxAlQgre3pcQcaRUm/8A0v/X8d2nhfraWSFqVmMcBcU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6d41bc27aaf7b6a3ba6b169db3bd5d6159cfaa47",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1769909678,
|
||||
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "72716169fe93074c333e8d0173151350670b824c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"bun2nix": "bun2nix",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"bun2nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1770228511,
|
||||
"narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "337a4fe074be1042a35086f15481d763b8ddc0e7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
19
flake.nix
Normal file
19
flake.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
description = "NixOS module for running Wafrn";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
bun2nix.url = "github:nix-community/bun2nix";
|
||||
bun2nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, bun2nix, ... }: {
|
||||
nixosModules = {
|
||||
wafrn = { ... }: {
|
||||
imports = [ ./modules/wafrn.nix ];
|
||||
_module.args.bun2nixFlake = bun2nix;
|
||||
};
|
||||
default = self.nixosModules.wafrn;
|
||||
};
|
||||
};
|
||||
}
|
||||
457
modules/wafrn.nix
Normal file
457
modules/wafrn.nix
Normal file
@@ -0,0 +1,457 @@
|
||||
{ config, lib, pkgs, bun2nixFlake ? null, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
mapAttrsToList
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
optionalAttrs
|
||||
optionalString
|
||||
types;
|
||||
|
||||
cfg = config.services.wafrn;
|
||||
|
||||
toEnvString = value:
|
||||
if builtins.isBool value then
|
||||
(if value then "true" else "false")
|
||||
else if builtins.isInt value || builtins.isFloat value then
|
||||
toString value
|
||||
else
|
||||
value;
|
||||
|
||||
quoteEnv = value:
|
||||
let
|
||||
s = toEnvString value;
|
||||
escaped = lib.replaceStrings [ "\\" "\"" "\n" "\r" ] [ "\\\\" "\\\"" "\\n" "" ] s;
|
||||
in
|
||||
"\"${escaped}\"";
|
||||
|
||||
baseEnv = {
|
||||
ADMIN_USER = "admin";
|
||||
ADMIN_EMAIL = "admin@example.com";
|
||||
ADMIN_PASSWORD = "change-me";
|
||||
|
||||
JWT_SECRET = "change-me";
|
||||
|
||||
DOMAIN_NAME = "wafrn.example.com";
|
||||
CACHE_DOMAIN = "cache.wafrn.example.com";
|
||||
MEDIA_DOMAIN = "media.wafrn.example.com";
|
||||
FRONTEND_MEDIA_URL = "https://media.wafrn.example.com";
|
||||
FRONTEND_CACHE_URL = "https://cache.wafrn.example.com/api/cache?media=";
|
||||
FRONTEND_FQDN_URL = "https://wafrn.example.com";
|
||||
|
||||
FRONTEND_SHORT_TITLE = "Wafrn";
|
||||
FRONTEND_LONG_TITLE = "Wafrn, the social media that respects you";
|
||||
FRONTEND_DESCRIPTION = "Wafrn is a federated social media inspired by tumblr that connects with the fediverse and bluesky";
|
||||
|
||||
DONATION_URL = "https://wafrn.example.com/about";
|
||||
|
||||
REGISTRATION_LEVEL = "PUBLIC";
|
||||
REGISTRATIONS_DISABLED_TEXT = "This instance is a private instance, and does not allow registrations";
|
||||
REVIEW_REGISTRATIONS = true;
|
||||
REGISTRATION_MINIMUM_AGE = 18;
|
||||
BUBBLE_SERVERS_SHOW_TYPE = "PUBLIC";
|
||||
BLOCKED_SERVERS_SHOW_TYPE = "LOGGEDIN";
|
||||
AUTOFOLLOW_MAIN_ADMIN = true;
|
||||
|
||||
DISABLE_REQUIRE_SEND_EMAIL = false;
|
||||
SMTP_HOST = "smtp.example.com";
|
||||
SMTP_USER = "wafrn";
|
||||
SMTP_PORT = 587;
|
||||
SMTP_PASSWORD = "change-me";
|
||||
SMTP_FROM = "wafrn@example.com";
|
||||
|
||||
POSTGRES_USER = "root";
|
||||
POSTGRES_PASSWORD = "root";
|
||||
POSTGRES_DBNAME = "wafrn";
|
||||
POSTGRES_DB = "wafrn";
|
||||
|
||||
ACME_EMAIL = "admin@example.com";
|
||||
|
||||
WEBPUSH_EMAIL = "mailto:info@wafrn.net";
|
||||
WEBPUSH_PRIVATE = "";
|
||||
WEBPUSH_PUBLIC = "";
|
||||
|
||||
ENABLE_BSKY = cfg.bluesky.enable;
|
||||
PDS_DOMAIN_NAME = cfg.bluesky.pdsDomain;
|
||||
PDS_JWT_SECRET = "change-me";
|
||||
PDS_ADMIN_PASSWORD = "change-me";
|
||||
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX = "";
|
||||
|
||||
ENABLE_RAW_OUTPUT = false;
|
||||
LOG_SQL_QUERIES = "";
|
||||
UPLOAD_LIMIT = "";
|
||||
POSTS_PER_PAGE = "";
|
||||
LOG_LEVEL = "";
|
||||
BLOCKLIST_URI = "";
|
||||
FRONTEND_PATH = "";
|
||||
BLOCKED_IPS = "";
|
||||
IGNORE_BLOCK_HOSTS = "";
|
||||
FRONTEND_LOGO = "";
|
||||
FRONTEND_API_URL = "";
|
||||
FRONTEND_CACHE_BACKUP_URLS = "";
|
||||
FRONTEND_SHORTEN_POSTS = "3";
|
||||
FRONTEND_DISABLE_PWA = false;
|
||||
FRONTEND_MAINTENANCE = false;
|
||||
};
|
||||
|
||||
effectiveEnv = baseEnv // cfg.environment;
|
||||
|
||||
envFileContents =
|
||||
concatStringsSep "\n" (mapAttrsToList (name: value: "${name}=${quoteEnv value}") effectiveEnv) + "\n";
|
||||
|
||||
envTemplate = pkgs.writeText "wafrn.env.base" envFileContents;
|
||||
|
||||
serviceEnvFile = "${cfg.stateDir}/.env";
|
||||
composeFile = "${cfg.stateDir}/docker-compose.yml";
|
||||
bunNixFile = "${cfg.stateDir}/${cfg.bun2nix.outputFile}";
|
||||
sourcePath = cfg.source;
|
||||
|
||||
bun2nixCli =
|
||||
if bun2nixFlake != null then
|
||||
"${bun2nixFlake.packages.${pkgs.system}.default}/bin/bun2nix"
|
||||
else
|
||||
"${pkgs.bun}/bin/bunx bun2nix";
|
||||
|
||||
serviceCommon = {
|
||||
restart = "unless-stopped";
|
||||
env_file = [ serviceEnvFile ];
|
||||
};
|
||||
|
||||
backendBuild = {
|
||||
context = sourcePath;
|
||||
dockerfile = "packages/backend/Dockerfile";
|
||||
};
|
||||
|
||||
backendService = {
|
||||
build = backendBuild;
|
||||
depends_on = {
|
||||
db = { condition = "service_started"; };
|
||||
redis = { condition = "service_started"; };
|
||||
frontend = { condition = "service_started"; };
|
||||
migration = { condition = "service_completed_successfully"; };
|
||||
};
|
||||
environment = {
|
||||
NODE_ENV = "production";
|
||||
USE_WORKERS = "true";
|
||||
};
|
||||
volumes = [
|
||||
"${cfg.stateDir}/uploads:/app/packages/backend/uploads"
|
||||
"${cfg.stateDir}/cache:/app/packages/backend/cache"
|
||||
"${cfg.stateDir}/frontend:/app/packages/frontend:ro"
|
||||
];
|
||||
};
|
||||
|
||||
composeConfig = {
|
||||
services = {
|
||||
backend = serviceCommon // backendService;
|
||||
|
||||
migration = serviceCommon // backendService // {
|
||||
restart = "no";
|
||||
depends_on = {
|
||||
db = { condition = "service_started"; };
|
||||
redis = { condition = "service_started"; };
|
||||
frontend = { condition = "service_started"; };
|
||||
};
|
||||
command = "npm exec tsx migrate.ts init-container";
|
||||
};
|
||||
|
||||
frontend = serviceCommon // {
|
||||
build = {
|
||||
context = sourcePath;
|
||||
dockerfile = "packages/frontend/Dockerfile";
|
||||
};
|
||||
restart = "unless-stopped";
|
||||
ports = publishedPorts;
|
||||
extra_hosts = [ "host.docker.internal:host-gateway" ];
|
||||
volumes = [
|
||||
"${cfg.stateDir}/caddy:/data"
|
||||
"${cfg.stateDir}/frontend:/var/www/html/frontend"
|
||||
"${cfg.stateDir}/uploads:/var/www/html/uploads"
|
||||
"${sourcePath}/packages/caddy:/etc/caddy/config"
|
||||
];
|
||||
};
|
||||
|
||||
db = {
|
||||
image = "postgres:17";
|
||||
restart = "unless-stopped";
|
||||
shm_size = "2gb";
|
||||
env_file = [ serviceEnvFile ];
|
||||
environment = {
|
||||
POSTGRES_DB = "${effectiveEnv.POSTGRES_DBNAME}";
|
||||
};
|
||||
volumes = [ "${cfg.stateDir}/postgres:/var/lib/postgresql/data" ];
|
||||
};
|
||||
|
||||
redis = {
|
||||
image = "redis:7.2.4";
|
||||
restart = "unless-stopped";
|
||||
volumes = [ "${cfg.stateDir}/redis:/data" ];
|
||||
};
|
||||
}
|
||||
// optionalAttrs cfg.adminer.enable {
|
||||
adminer = {
|
||||
image = "adminer";
|
||||
restart = "unless-stopped";
|
||||
};
|
||||
}
|
||||
// optionalAttrs cfg.bluesky.enable {
|
||||
pds_worker = serviceCommon // {
|
||||
build = backendBuild;
|
||||
command = "npm exec tsx atproto.ts";
|
||||
depends_on = {
|
||||
db = { condition = "service_started"; };
|
||||
redis = { condition = "service_started"; };
|
||||
migration = { condition = "service_completed_successfully"; };
|
||||
};
|
||||
environment = {
|
||||
NODE_ENV = "production";
|
||||
USE_WORKERS = "true";
|
||||
};
|
||||
volumes = [
|
||||
"${cfg.stateDir}/uploads:/app/packages/backend/uploads"
|
||||
"${cfg.stateDir}/cache:/app/packages/backend/cache"
|
||||
"${cfg.stateDir}/frontend:/app/packages/frontend:ro"
|
||||
];
|
||||
};
|
||||
}
|
||||
// optionalAttrs (cfg.bluesky.enable && cfg.bluesky.useBundledPds) {
|
||||
pds = {
|
||||
image = "ghcr.io/bluesky-social/pds:0.4";
|
||||
restart = "unless-stopped";
|
||||
env_file = [ serviceEnvFile ];
|
||||
environment = {
|
||||
PDS_DATA_DIRECTORY = "/pds";
|
||||
PDS_BLOBSTORE_DISK_LOCATION = "/pds/blocks";
|
||||
PDS_BLOB_UPLOAD_LIMIT = "157286400";
|
||||
PDS_DID_PLC_URL = "https://plc.directory";
|
||||
PDS_BSKY_APP_VIEW_URL = "https://api.bsky.app";
|
||||
PDS_BSKY_APP_VIEW_DID = "did:web:api.bsky.app";
|
||||
PDS_REPORT_SERVICE_URL = "https://mod.bsky.app";
|
||||
PDS_REPORT_SERVICE_DID = "did:plc:ar7c4by46qjdydhdevvrndac";
|
||||
PDS_CRAWLERS = "https://bsky.network, https://atproto.africa";
|
||||
PDS_EMAIL_SMTP_URL = "smtps://${effectiveEnv.SMTP_USER}:${effectiveEnv.SMTP_PASSWORD}@${toString effectiveEnv.SMTP_HOST}:${toString effectiveEnv.SMTP_PORT}";
|
||||
PDS_EMAIL_FROM_ADDRESS = "${effectiveEnv.SMTP_FROM}";
|
||||
LOG_ENABLED = "true";
|
||||
};
|
||||
volumes = [ "${cfg.stateDir}/pds:/pds" ];
|
||||
};
|
||||
};
|
||||
|
||||
networks = {
|
||||
default = {
|
||||
enable_ipv6 = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
composeTemplate = pkgs.writeText "wafrn-compose.yml" (lib.generators.toYAML { } composeConfig);
|
||||
|
||||
composeCmd = "${pkgs.docker-compose}/bin/docker-compose";
|
||||
in
|
||||
{
|
||||
options.services.wafrn = {
|
||||
enable = mkEnableOption "Wafrn social platform";
|
||||
|
||||
source = mkOption {
|
||||
type = types.str;
|
||||
example = "/srv/wafrn";
|
||||
description = "Path to a Wafrn source checkout (used as Docker build context).";
|
||||
};
|
||||
|
||||
stateDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/wafrn";
|
||||
description = "Persistent state directory for databases, uploads, caddy data, and optional PDS data.";
|
||||
};
|
||||
|
||||
composeProjectName = mkOption {
|
||||
type = types.str;
|
||||
default = "wafrn";
|
||||
description = "Docker Compose project name.";
|
||||
};
|
||||
|
||||
secretsFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/run/secrets/wafrn.env";
|
||||
description = "Optional dotenv file with secret overrides appended at runtime.";
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = types.attrsOf (types.oneOf [ types.str types.int types.float types.bool ]);
|
||||
default = { };
|
||||
description = "Non-secret environment overrides written to the generated .env file.";
|
||||
};
|
||||
|
||||
httpPort = mkOption {
|
||||
type = types.nullOr types.port;
|
||||
default = 80;
|
||||
description = "Host port mapped to Wafrn HTTP (container port 80). Set to null to disable publishing HTTP.";
|
||||
};
|
||||
|
||||
httpsPort = mkOption {
|
||||
type = types.nullOr types.port;
|
||||
default = 443;
|
||||
description = "Host port mapped to Wafrn HTTPS (container port 443). Set to null to disable publishing HTTPS.";
|
||||
};
|
||||
|
||||
autoBuild = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to pass --build when starting containers.";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Open configured HTTP/HTTPS ports in the NixOS firewall.";
|
||||
};
|
||||
|
||||
adminer.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable Adminer container.";
|
||||
};
|
||||
|
||||
bun2nix = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Generate a bun2nix expression from the Wafrn bun lock file before starting.";
|
||||
};
|
||||
|
||||
lockFile = mkOption {
|
||||
type = types.str;
|
||||
default = "bun.lock";
|
||||
description = "Lock file path relative to services.wafrn.source.";
|
||||
};
|
||||
|
||||
outputFile = mkOption {
|
||||
type = types.str;
|
||||
default = "bun.nix";
|
||||
description = "Generated bun2nix expression filename under services.wafrn.stateDir.";
|
||||
};
|
||||
|
||||
copyPrefix = mkOption {
|
||||
type = types.str;
|
||||
default = "./";
|
||||
description = "Value passed to bun2nix --copy-prefix for workspace/file dependencies.";
|
||||
};
|
||||
};
|
||||
|
||||
bluesky = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable Bluesky integration and ATProto worker.";
|
||||
};
|
||||
|
||||
useBundledPds = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Run Wafrn's bundled Bluesky PDS container. Set false to use an external PDS.";
|
||||
};
|
||||
|
||||
pdsDomain = mkOption {
|
||||
type = types.str;
|
||||
default = "bsky.example.com";
|
||||
description = "PDS domain used by Wafrn (can point to an external PDS).";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = config.virtualisation.docker.enable;
|
||||
message = "services.wafrn requires virtualisation.docker.enable = true;";
|
||||
}
|
||||
{
|
||||
assertion = cfg.httpPort != null || cfg.httpsPort != null;
|
||||
message = "services.wafrn requires at least one published port (httpPort or httpsPort).";
|
||||
}
|
||||
{
|
||||
assertion = (!cfg.bun2nix.enable) || (bun2nixFlake != null);
|
||||
message = "services.wafrn.bun2nix.enable requires using this module from the flake output so bun2nix is available.";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.stateDir} 0750 root root -"
|
||||
"d ${cfg.stateDir}/postgres 0750 root root -"
|
||||
"d ${cfg.stateDir}/redis 0750 root root -"
|
||||
"d ${cfg.stateDir}/uploads 0750 root root -"
|
||||
"d ${cfg.stateDir}/cache 0750 root root -"
|
||||
"d ${cfg.stateDir}/caddy 0750 root root -"
|
||||
"d ${cfg.stateDir}/frontend 0750 root root -"
|
||||
] ++ lib.optionals (cfg.bluesky.enable && cfg.bluesky.useBundledPds) [
|
||||
"d ${cfg.stateDir}/pds 0750 root root -"
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall firewallPorts;
|
||||
|
||||
systemd.services.wafrn-prepare = {
|
||||
description = "Prepare Wafrn runtime files";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "wafrn.service" ];
|
||||
after = [ "docker.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
${optionalString cfg.bun2nix.enable ''
|
||||
if [ ! -f "${cfg.source}/${cfg.bun2nix.lockFile}" ]; then
|
||||
echo "missing lockfile: ${cfg.source}/${cfg.bun2nix.lockFile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
${bun2nixCli} \
|
||||
--lock-file "${cfg.source}/${cfg.bun2nix.lockFile}" \
|
||||
--output-file "${bunNixFile}" \
|
||||
--copy-prefix "${cfg.bun2nix.copyPrefix}"
|
||||
''}
|
||||
|
||||
install -m 0600 ${envTemplate} ${serviceEnvFile}
|
||||
${optionalString (cfg.secretsFile != null) ''
|
||||
cat "${cfg.secretsFile}" >> ${serviceEnvFile}
|
||||
''}
|
||||
install -m 0644 ${composeTemplate} ${composeFile}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.wafrn = {
|
||||
description = "Wafrn Docker Compose stack";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "docker.service" "wafrn-prepare.service" ];
|
||||
after = [ "docker.service" "wafrn-prepare.service" ];
|
||||
path = [ pkgs.docker-compose pkgs.coreutils ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
WorkingDirectory = cfg.stateDir;
|
||||
};
|
||||
|
||||
script = ''
|
||||
${composeCmd} --project-name ${cfg.composeProjectName} --file ${composeFile} up -d ${optionalString cfg.autoBuild "--build"}
|
||||
'';
|
||||
|
||||
preStop = ''
|
||||
${composeCmd} --project-name ${cfg.composeProjectName} --file ${composeFile} down
|
||||
'';
|
||||
|
||||
reload = ''
|
||||
${composeCmd} --project-name ${cfg.composeProjectName} --file ${composeFile} up -d ${optionalString cfg.autoBuild "--build"}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
publishedPorts =
|
||||
lib.optionals (cfg.httpPort != null) [ "${toString cfg.httpPort}:80" ]
|
||||
++ lib.optionals (cfg.httpsPort != null) [ "${toString cfg.httpsPort}:443" ];
|
||||
|
||||
firewallPorts =
|
||||
lib.optionals (cfg.httpPort != null) [ cfg.httpPort ]
|
||||
++ lib.optionals (cfg.httpsPort != null) [ cfg.httpsPort ];
|
||||
Reference in New Issue
Block a user