diff --git a/nixos/arion-paperless/arion-compose.nix b/nixos/arion-paperless/arion-compose.nix new file mode 100644 index 0000000..51e028d --- /dev/null +++ b/nixos/arion-paperless/arion-compose.nix @@ -0,0 +1,73 @@ +{ pkgs, ... }: +{ + project.name = "paperless"; + + networks.paperless.external = false; + + services = { + redis = { + service = { + image = "redis:7"; + container_name = "paperless-redis"; + restart = "unless-stopped"; + networks = [ "paperless" ]; + volumes = [ + "/var/paperless/redis:/data" + ]; + }; + }; + + db = { + service = { + image = "postgres:16"; + container_name = "paperless-db"; + restart = "unless-stopped"; + networks = [ "paperless" ]; + volumes = [ + "/var/paperless/postgres:/var/lib/postgresql/data" + ]; + environment = { + POSTGRES_DB = "paperless"; + POSTGRES_USER = "paperless"; + POSTGRES_PASSWORD = "paperless"; + }; + healthcheck = { + test = [ "CMD-SHELL" "pg_isready -U paperless -d paperless" ]; + interval = "5s"; + timeout = "5s"; + retries = 20; + }; + }; + }; + + webserver = { + service = { + image = "ghcr.io/paperless-ngx/paperless-ngx:latest"; + container_name = "paperless-ngx"; + restart = "unless-stopped"; + networks = [ "paperless" ]; + depends_on = [ "db" "redis" ]; + ports = [ "127.0.0.1:8000:8000" ]; + volumes = [ + "/var/paperless/data:/usr/src/paperless/data" + "/var/paperless/media:/usr/src/paperless/media" + "/var/paperless/export:/usr/src/paperless/export" + "/var/paperless/consume:/usr/src/paperless/consume" + ]; + environment = { + PAPERLESS_REDIS = "redis://redis:6379"; + PAPERLESS_DBHOST = "db"; + PAPERLESS_DBNAME = "paperless"; + PAPERLESS_DBUSER = "paperless"; + PAPERLESS_DBPASS = "paperless"; + PAPERLESS_URL = "https://paperless.philippeterson.com"; + PAPERLESS_TIME_ZONE = "America/Anchorage"; + PAPERLESS_OCR_LANGUAGE = "eng"; + USERMAP_UID = "1000"; + USERMAP_GID = "1000"; + }; + env_file = [ "/run/agenix/paperless" ]; + }; + }; + }; +} diff --git a/nixos/arion-paperless/arion-pkgs.nix b/nixos/arion-paperless/arion-pkgs.nix new file mode 100644 index 0000000..1d16305 --- /dev/null +++ b/nixos/arion-paperless/arion-pkgs.nix @@ -0,0 +1,3 @@ +import { + system = "x86_64-linux"; +} diff --git a/nixos/linux.nix b/nixos/linux.nix index 825bb1b..0a48795 100644 --- a/nixos/linux.nix +++ b/nixos/linux.nix @@ -78,6 +78,11 @@ in { file = ./secrets/vnc-htpasswd.age; owner = "nginx"; }; + + paperless = { + file = ./secrets/paperless.age; + owner = "root"; + }; }; environment.systemPackages = [ @@ -164,6 +169,7 @@ in { projects.forgejo.settings = import ./arion/arion-compose.nix; projects.riverside.settings = import ./arion-riverside/arion-compose.nix; projects.pluto.settings = import ./arion-pluto/arion-compose.nix; + projects.paperless.settings = import ./arion-paperless/arion-compose.nix; }; # The arion NixOS module sets backend = "podman-socket" but doesn't inject @@ -172,6 +178,7 @@ in { systemd.services.arion-forgejo.environment.DOCKER_HOST = "unix:///run/podman/podman.sock"; systemd.services.arion-riverside.environment.DOCKER_HOST = "unix:///run/podman/podman.sock"; systemd.services.arion-pluto.environment.DOCKER_HOST = "unix:///run/podman/podman.sock"; + systemd.services.arion-paperless.environment.DOCKER_HOST = "unix:///run/podman/podman.sock"; # Build the VNC desktop image locally from the Dockerfile — no registry push/pull needed. # vncContext is a Nix store path that changes whenever any file under vnc-desktop/ changes, @@ -241,6 +248,12 @@ in { "d /root/.config 0755 ${username} users" "d /var/pluto/notebooks 0755 root root" "d /var/pluto/julia-depot 0755 root root" + "d /var/paperless/data 0755 root root" + "d /var/paperless/media 0755 root root" + "d /var/paperless/export 0755 root root" + "d /var/paperless/consume 0755 root root" + "d /var/paperless/postgres 0755 root root" + "d /var/paperless/redis 0755 root root" "d /var/riverside/files 0755 root root" "d /var/riverside/postgres 0755 root root" "d /var/lib/gitea-runner/ubuntu 0755 gitea-runner gitea-runner" @@ -431,6 +444,13 @@ in { webroot = null; group = config.services.nginx.group; }; + + certs."paperless.philippeterson.com" = { + dnsProvider = "nearlyfreespeech"; + environmentFile = config.age.secrets."nearlyfreespeech".path; + webroot = null; + group = config.services.nginx.group; + }; }; # Break the systemd ordering cycle that deadlocks nixos-rebuild switch. @@ -454,5 +474,6 @@ in { "acme-selfsigned-vnc.quinefoundation.com.service" "acme-selfsigned-webdav.philippeterson.com.service" "acme-selfsigned-pluto.philippeterson.com.service" + "acme-selfsigned-paperless.philippeterson.com.service" ]; } diff --git a/nixos/nginx.nix b/nixos/nginx.nix index c4fcd30..8fc7c9f 100644 --- a/nixos/nginx.nix +++ b/nixos/nginx.nix @@ -114,6 +114,22 @@ }; }; + "paperless.philippeterson.com" = { + useACMEHost = "paperless.philippeterson.com"; + onlySSL = true; + + locations."/" = { + proxyPass = "http://127.0.0.1:8000/"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + client_max_body_size 100M; + ''; + }; + }; + "pluto.philippeterson.com" = { useACMEHost = "pluto.philippeterson.com"; onlySSL = true; diff --git a/nixos/secrets/default.nix b/nixos/secrets/default.nix index 8c9565f..366a9ab 100644 --- a/nixos/secrets/default.nix +++ b/nixos/secrets/default.nix @@ -24,4 +24,10 @@ in { # htpasswd-format credentials for nginx basic auth on vnc.quinefoundation.com # Generate with: htpasswd -n "./vnc-htpasswd.age".publicKeys = [mainframePublicKey]; + + # PAPERLESS_SECRET_KEY= + # PAPERLESS_ADMIN_USER=admin + # PAPERLESS_ADMIN_PASSWORD= + # PAPERLESS_ADMIN_EMAIL=peterson@sent.com + "./paperless.age".publicKeys = [mainframePublicKey]; }