<template>
        let

        # add nginx reverse proxy and ACME web certificate
        add_nginx = true;
        nginx_ports = [ 80 443 ];

        lemmy = {
        upstreamName = "lemmy";
        dataDir = "/var/lib/lemmy";
        ip = "127.0.0.1";
        port = 1234;
        # TODO: Change this domain to your own
        domain = "lemmy.example.com";
        };

        lemmy-ui = {
        upstreamName = "lemmy-ui";
        ip = "127.0.0.1";
        port = 8536;
        };

        pict-rs = {
        ip = "127.0.0.1";
        port = 8080;
        };

        acmeDomain = lemmy.domain;
        nginxVhost = lemmy.domain;

        in {

        security.acme = lib.mkIf add_nginx {
        # TODO: change this to true if you accept
        acceptTerms = false;
        defaults = {
        # TODO: you will receive a notification if automatic certificate renewal fails
        email = "postmaster@${lemmy.domain}";
        # TODO: put your dns provider here: https://go-acme.github.io/lego/dns/
        dnsProvider = "";
        # TODO: this file should contain environment variables expected by your dns provider
        credentialsFile = "";
        };
        certs."${acmeDomain}" = {
        domain = "${acmeDomain}";
        };
        };

        networking.firewall.allowedTCPPorts = lib.mkIf add_nginx nginx_ports;

        # is needed because of certificate file permissions
        users.users.nginx.extraGroups = lib.mkIf add_nginx ["acme"];

        services.nginx = lib.mkIf add_nginx {
        upstreams."${lemmy.upstreamName}".servers."${lemmy.ip}:${builtins.toString lemmy.port}" = {};
        upstreams."${lemmy-ui.upstreamName}".servers."${lemmy-ui.ip}:${builtins.toString lemmy-ui.port}" = {};

        virtualHosts."${nginxVhost}" = {
        useACMEHost = "${acmeDomain}";
        # inherit from config.security.acme.acmeRoot;
        acmeRoot = null;
        # add redirects from http to https
        forceSSL = true;
        # this whole block was lifted from
        https://github.com/LemmyNet/lemmy/blob/ef1aa18fd20cc03d492a81cb70cc75cf3281649f/docker/nginx.conf#L21 lines
        21-32
        extraConfig = ''
        # disables emitting nginx version on error pages and in the “Server” response header field
        server_tokens off;

        gzip on;
        gzip_types text/css application/javascript image/svg+xml;
        gzip_vary on;

        # Upload limit, relevant for pictrs
        client_max_body_size 20M;

        add_header X-Frame-Options SAMEORIGIN;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        '';

        locations = {
        "/" = {
        extraConfig = ''
        # distinguish between ui requests and backend
        # don't change lemmy-ui or lemmy here, they refer to the upstream definitions on top
        set $proxpass "http://${lemmy-ui.upstreamName}";

        if ($http_accept = "application/activity+json") {
        set $proxpass "http://${lemmy.upstreamName}";
        }
        if ($http_accept = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") {
        set $proxpass "http://${lemmy.upstreamName}";
        }
        if ($request_method = POST) {
        set $proxpass "http://${lemmy.upstreamName}";
        }
        proxy_pass $proxpass;

        # Cuts off the trailing slash on URLs to make them valid
        rewrite ^(.+)/+$ $1 permanent;

        # Send actual client IP upstream
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        '';
        };

        # again, lifted wholesale from
        https://github.com/LemmyNet/lemmy/blob/ef1aa18fd20cc03d492a81cb70cc75cf3281649f/docker/nginx.conf#L60 lines
        60-69 (nice!)
        "~ ^/(api|pictrs|feeds|nodeinfo|.well-known)" = {
        proxyPass = "http://${lemmy.upstreamName}";
        extraConfig = ''
        # proxy common stuff
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        ## Send actual client IP upstream
        #proxy_set_header X-Real-IP $remote_addr;
        #proxy_set_header Host $host;
        #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        '';
        };
        };
        };
        };

        systemd.services.lemmy-ui = {
        environment = {
        LEMMY_UI_HOST = lib.mkForce "${lemmy-ui.ip}:${toString lemmy-ui.port}";
        LEMMY_UI_LEMMY_INTERNAL_HOST = lib.mkForce "${lemmy.ip}:${toString lemmy.port}";
        LEMMY_UI_LEMMY_EXTERNAL_HOST = lib.mkForce lemmy.domain ;
        LEMMY_UI_HTTPS="true";
        };
        };

        services.pict-rs = {
        enable = true;
        port = pict-rs.port;
        dataDir = "${dataDir}/pict-rs";
        address = pict-rs.ip;
        };

        systemd.services.lemmy = {
        requires = ["postgresql.service"];
        after = ["postgresql.service"];
        environment = {
        LEMMY_DATABASE_URL = lib.mkForce "postgresql://lemmy@127.0.0.1:${toString
        config.services.postgresql.port}/lemmy";
        };
        };

        services.lemmy = {
        enable = true;
        ui.port = lemmy-ui.port;
        database.createLocally = true;
        settings = {
        # TODO: Enable this much later when you tested everything.
        # N.B. you can't change your domain name after enabling this.
        federation.enabled = false;
        # settings related to the postgresql database
        database = {
        user = "lemmy";
        password = "secretlemmypassword";
        host = "127.0.0.1";
        port = ${config.services.postgresql.port};
        database = "lemmy";
        pool_size = 5;
        };
        # Pictrs image server configuration.
        pictrs = {
        # Address where pictrs is available (for image hosting)
        url = "http://${pict-rs.ip}:${toString pict-rs.port}/";
        # TODO: Set a custom pictrs API key. ( Required for deleting images )
        api_key = "";
        };
        # TODO: Email sending configuration. All options except login/password are mandatory
        email = {
        # Hostname and port of the smtp server
        smtp_server = "";
        # Login name for smtp server
        smtp_login = "";
        # Password to login to the smtp server
        smtp_password = "";
        # Address to send emails from, eg "noreply@your-instance.com";
        smtp_from_address = "noreply@${lemmy.domain}";
        # Whether or not smtp connections should use tls. Can be none, tls, or starttls
        tls_type = "none";
        };
        # TODO: Parameters for automatic configuration of new instance (only used at first start)
        setup = {
        # Username for the admin user
        admin_username = "superawesomeadmin";
        # Password for the admin user. It must be at least 10 characters.
        admin_password = "";
        # Name of the site (can be changed later)
        site_name = "Lemmy at ${lemmy.domain}";
        # Email for the admin user (optional, can be omitted and set later through the website)
        admin_email = "admin@${lemmy.domain}";
        };
        # the domain name of your instance (mandatory)
        hostname = lemmy.domain;
        # Address where lemmy should listen for incoming requests
        bind = lemmy.ip;
        # Port where lemmy should listen for incoming requests
        port = lemmy.port;
        # Whether the site is available over TLS. Needs to be true for federation to work.
        tls_enabled = true;
        };

        };


        # needed for now
        nixpkgs.config.permittedInsecurePackages = [
        "nodejs-14.21.3"
        "openssl-1.1.1t"
        ];

        system.activationScripts."make_sure_lemmy_user_owns_files" = ''
        uid='${config.users.users.lemmy.uid}';
        gid='${config.users.groups.lemmy.gid}';
        dir='${lemmy.dataDir}'

        mkdir -p "''${dir}"

        if [[ "$(${pkgs.toybox}/bin/stat "''${dir}" -c '%u:%g' | tee /dev/stderr )" != "''${uid}:''${gid}" ]]; then
        chown -R "''${uid}:''${gid}" "''${dir}"
        fi
        '';
        };
        };
        }

</template>

