# OpenPost - Multi-platform social media posting # https://github.com/rodrgds/openpost { config, lib, pkgs, ... }: let cfg = config.vps.openpost; # Host port (external) - must be unique per service openpostHostPort = 8090; # Container port (internal) - OpenPost listens on 8080 inside container openpostContainerPort = 8080; in { options.vps.openpost = { enable = lib.mkEnableOption "OpenPost social media scheduler"; domain = lib.mkOption { type = lib.types.str; default = "openpost.rgo.pt"; description = "Domain for OpenPost"; }; timezone = lib.mkOption { type = lib.types.str; default = "Europe/Lisbon"; description = "Timezone for OpenPost"; }; }; config = lib.mkIf cfg.enable { # Create persistent directories # Note: Container runs as user 'openpost' (UID 1000) systemd.tmpfiles.rules = [ "d /var/lib/openpost 0755 root root -" "d /var/lib/openpost/data 0755 1000 1000 -" "d /var/lib/openpost/data/db 0755 1000 1000 -" "d /var/lib/openpost/data/media 0755 1000 1000 -" ]; # OpenPost application virtualisation.oci-containers.containers.openpost = { image = "ghcr.io/rodrgds/openpost:latest"; environment = { OPENPOST_PORT = toString openpostContainerPort; OPENPOST_DB_PATH = "/data/db/openpost.db"; OPENPOST_MEDIA_PATH = "/data/media"; OPENPOST_MEDIA_URL = "https://${cfg.domain}/media"; OPENPOST_FRONTEND_URL = "https://${cfg.domain}"; OPENPOST_CORS_EXTRA_ORIGINS = "https://${cfg.domain}"; OPENPOST_DISABLE_LINKEDIN_THREAD_REPLIES = "true"; TZ = cfg.timezone; }; environmentFiles = [ config.sops.templates.openpost-env.path ]; volumes = [ "/var/lib/openpost/data:/data" ]; ports = [ "127.0.0.1:${toString openpostHostPort}:${toString openpostContainerPort}" ]; extraOptions = [ "--network=podman" "--health-cmd=wget --spider http://localhost:${toString openpostContainerPort}/api/v1/health" "--health-interval=30s" "--health-timeout=3s" "--health-retries=3" ]; }; # Secrets sops.templates = { "openpost-env" = { content = '' JWT_SECRET=${config.sops.placeholder.openpost_jwt_secret} ENCRYPTION_KEY=${config.sops.placeholder.openpost_encryption_key} TWITTER_CLIENT_ID=${config.sops.placeholder.openpost_twitter_client_id} TWITTER_CLIENT_SECRET=${config.sops.placeholder.openpost_twitter_client_secret} TWITTER_REDIRECT_URI=https://${cfg.domain}/api/v1/accounts/x/callback LINKEDIN_CLIENT_ID=${config.sops.placeholder.openpost_linkedin_client_id} LINKEDIN_CLIENT_SECRET=${config.sops.placeholder.openpost_linkedin_client_secret} LINKEDIN_REDIRECT_URI=https://${cfg.domain}/api/v1/accounts/linkedin/callback THREADS_CLIENT_ID=${config.sops.placeholder.openpost_threads_client_id} THREADS_CLIENT_SECRET=${config.sops.placeholder.openpost_threads_client_secret} THREADS_REDIRECT_URI=https://${cfg.domain}/api/v1/accounts/threads/callback MASTODON_REDIRECT_URI=https://${cfg.domain}/api/v1/accounts/mastodon/callback MASTODON_SERVERS=${config.sops.placeholder.openpost_mastodon_servers} ''; mode = "0444"; }; }; # Caddy reverse proxy vps.caddy.internalPorts.openpost = openpostHostPort; }; }