this post was submitted on 10 Jan 2025
82 points (95.6% liked)

Selfhosted

41084 readers
273 users here now

A place to share alternatives to popular online services that can be self-hosted without giving up privacy or locking you into a service you don't control.

Rules:

  1. Be civil: we're here to support and learn from one another. Insults won't be tolerated. Flame wars are frowned upon.

  2. No spam posting.

  3. Posts have to be centered around self-hosting. There are other communities for discussing hardware or home computing. If it's not obvious why your post topic revolves around selfhosting, please include details to make it clear.

  4. Don't duplicate the full text of your blog or github here. Just post the link for folks to click.

  5. Submission headline should match the article title (don’t cherry-pick information from the title to fit your agenda).

  6. No trolling.

Resources:

Any issues on the community? Report it using the report flag.

Questions? DM the mods!

founded 2 years ago
MODERATORS
 

tldr: I'd like to set up a reverse proxy with a domain and an SSL cert so my partner and I can access a few selfhosted services on the internet but I'm not sure what the best/safest way to do it is. Asking my partner to use tailsclae or wireguard is asking too much unfortunately. I was curious to know what you all recommend.

I have some services running on my LAN that I currently access via tailscale. Some of these services would see some benefit from being accessible on the internet (ex. Immich sharing via a link, switching over from Plex to Jellyfin without requiring my family to learn how to use a VPN, homeassistant voice stuff, etc.) but I'm kind of unsure what the best approach is. Hosting services on the internet has risk and I'd like to reduce that risk as much as possible.

  1. I know a reverse proxy would be beneficial here so I can put all the services on one box and access them via subdomains but where should I host that proxy? On my LAN using a dynamic DNS service? In the cloud? If in the cloud, should I avoid a plan where you share cpu resources with other users and get a dedicated box?

  2. Should I purchase a memorable domain or a domain with a random string of characters so no one could reasonably guess it? Does it matter?

  3. What's the best way to geo-restrict access? Fail2ban? Realistically, the only people that I might give access to live within a couple hundred miles of me.

  4. Any other tips or info you care to share would be greatly appreciated.

  5. Feel free to talk me out of it as well.

you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 1 points 2 days ago (5 children)

i guess you were able to install the os ok? are you using proxmox or regular servers?

I was. It was learning the Nix way of doing things that was just taking more time than i had anticipated. I'll get around to it eventually though

I tried out proxmox years ago but besides the web interface, I didn't understand why I should use it over Debian or Ubuntu. At the moment, I'm just using Ubuntu and docker containers. In previous setups, I was using KVMs too.

Correct me if I'm wrong, but don't you have to reboot every time you change your Nix config? That was what was painful. Once it's set up the way you want, it seemed great but getting to that point for a beginner was what put me off.

I would be interested to see the config though

[–] [email protected] 1 points 1 day ago

i have found this reference very useful https://mynixos.com/options/

[–] [email protected] 1 points 1 day ago

yeah proxmox is not necessary unless you need lots of separate instances to play around with

[–] [email protected] 1 points 1 day ago* (last edited 1 day ago)

this is my container config for element/matrix podman containers do not run as root so you have to get the file privileges right on the volumes mapped into the containers. i used top to find out what user the services were running as. you can see there are some settings there where you can change the user if you are having permissions problems




{ pkgs, modulesPath, ... }:

{

  imports = [
    (modulesPath + "/virtualisation/proxmox-lxc.nix")
  ];

  security.pki.certificateFiles = [ "/etc/ssl/certs/ca-certificates.crt" ];

  system.stateVersion = "23.11";
  system.autoUpgrade.enable = true;
  system.autoUpgrade.allowReboot = false;

  nix.gc = {
    automatic = true;
    dates = "weekly";
    options = "--delete-older-than 14d";
  };

  services.openssh = {
    enable = true;
    settings.PasswordAuthentication = true;
  };

  users.users.XXXXXX = {
    isNormalUser = true;
    home = "/home/XXXXXX";
    extraGroups = [ "wheel" ];
    shell = pkgs.zsh;
  };

  programs.zsh.enable = true;

  environment.etc = {
    "fail2ban/filter.d/matrix-synapse.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
      [Definition]
      failregex = .*POST.* - <HOST> - 8008.*\n.*\n.*Got login request.*\n.*Failed password login.*
                  .*POST.* - <HOST> - 8008.*\n.*\n.*Got login request.*\n.*Attempted to login as.*\n.*Invalid username or password.*
    '');
  };

  services.fail2ban = {
    enable = true;
    maxretry = 3;
    bantime = "10m";
    bantime-increment = {
      enable = true;
      multipliers = "1 2 4 8 16 32 64";
      maxtime = "168h";
      overalljails = true;
    };
    jails = {
      matrix-synapse.settings = {
        filter = "matrix-synapse";
        action = "%(known/action)s";
        logpath = "/srv/logs/synapse.json.log";
        backend = "auto";
        findtime = 600;
        bantime  = 600;
        maxretry = 2;
      };
    };
  };

  virtualisation.oci-containers = {
    containers = {

      postgres = {
        autoStart = false;
        environment = {
          POSTGRES_USER = "XXXXXX";
          POSTGRES_PASSWORD = "XXXXXX";
          LANG = "en_US.utf8";
        };
        image = "docker.io/postgres:14";
        ports = [ "5432:5432" ];
        volumes = [
          "/srv/postgres:/var/lib/postgresql/data"
        ];
        extraOptions = [
          "--label" "io.containers.autoupdate=registry"
          "--pull=newer"
        ];
      };

      synapse = {
        autoStart = false;
        environment = {
          LANG = "C.UTF-8";
#          UID="0";
#          GID="0";
        };
 #       user = "1001:1000";
        image = "ghcr.io/element-hq/synapse:latest";
        ports = [ "8008:8008" ];
        volumes = [
          "/srv/synapse:/data"
        ];
        log-driver = "json-file";
        extraOptions = [
          "--label" "io.containers.autoupdate=registry"
          "--log-opt" "max-size=10m" "--log-opt" "max-file=1" "--log-opt" "path=/srv/logs/synapse.json.log"
          "--pull=newer"
        ];
        dependsOn = [ "postgres" ];
      };

      element = {
        autoStart = true;
        image = "docker.io/vectorim/element-web:latest";
        ports = [ "8009:80" ];
        volumes = [
          "/srv/element/config.json:/app/config.json"
        ];
        extraOptions = [
          "--label" "io.containers.autoupdate=registry"
          "--pull=newer"
        ];
#        dependsOn = [ "synapse" ];
      };

      call = {
        autoStart = true;
        image = "ghcr.io/element-hq/element-call:latest-ci";
        ports = [ "8080:8080" ];
        volumes = [
          "/srv/call/config.json:/app/config.json"
        ];
        extraOptions = [
          "--label" "io.containers.autoupdate=registry"
          "--pull=newer"
        ];
      };

      livekit = {
        autoStart = true;
        image = "docker.io/livekit/livekit-server:latest";
        ports = [ "7880:7880" "7881:7881" "50000-60000:50000-60000/udp" "5349:5349" "3478:3478/udp" ];
        cmd = [ "--config" "/etc/config.yaml" ];
        entrypoint = "/livekit-server";
        volumes = [
          "/srv/livekit:/etc"
        ];
        extraOptions = [
          "--label" "io.containers.autoupdate=registry"
          "--pull=newer"
        ];
      };

      livekitjwt = {
        autoStart = true;
        image = "ghcr.io/element-hq/lk-jwt-service:latest-ci";
        ports = [ "7980:8080" ];
        environment = {
          LK_JWT_PORT = "8080";
          LIVEKIT_URL = "wss://livekit.xxxxxx.dynu.net/";
          LIVEKIT_KEY = "XXXXXX";
          LIVEKIT_SECRET = "XXXXXX";
        };
        entrypoint = "/lk-jwt-service";
        extraOptions = [
          "--label" "io.containers.autoupdate=registry"
          "--pull=newer"
        ];
      };

    };
  };

}




[–] [email protected] 1 points 1 day ago* (last edited 1 day ago)

this is my nginx config for my element/matrix services

as you can see i am using a proxmox NixOS with an old 23.11 nix channel but i'm sure the config can be used in other NixOS environments


{ pkgs, modulesPath, ... }:

{
  imports = [
    (modulesPath + "/virtualisation/proxmox-lxc.nix")
  ];

  security.pki.certificateFiles = [ "/etc/ssl/certs/ca-certificates.crt" ];

  system.stateVersion = "23.11";
  system.autoUpgrade.enable = true;
  system.autoUpgrade.allowReboot = true;

  nix.gc = {
    automatic = true;
    dates = "weekly";
    options = "--delete-older-than 14d";
  };

  networking.firewall.allowedTCPPorts = [ 80 443 ];

  services.openssh = {
    enable = true;
    settings.PasswordAuthentication = true;
  };

  users.users.XXXXXX = {
    isNormalUser = true;
    home = "/home/XXXXXX";
    extraGroups = [ "wheel" ];
    shell = pkgs.zsh;
  };

  programs.zsh.enable = true;

  security.acme = {
    acceptTerms = true;
    defaults.email = "[email protected]";
  };

  services.nginx = {
    enable = true;

    virtualHosts._ = {
      default = true;
      extraConfig = "return 500; server_tokens off;";
    };

    virtualHosts."XXXXXX.dynu.net" = {
      enableACME = true;
      addSSL = true;

      locations."/_matrix/federation/v1" = {
        proxyPass = "http://192.168.10.131:8008/";
        extraConfig = "client_max_body_size 300M;" +
          "proxy_set_header X-Forwarded-For $remote_addr;" +
          "proxy_set_header Host $host;" +
          "proxy_set_header X-Forwarded-Proto $scheme;";
      };

      locations."/" = {
        extraConfig = "return 302 https://element.xxxxxx.dynu.net/;";
      };

      extraConfig = "proxy_http_version 1.1;";
    };

    virtualHosts."matrix.XXXXXX.dynu.net" = {
      enableACME = true;
      addSSL = true;

      extraConfig = "proxy_http_version 1.1;";

      locations."/" = {
        proxyPass = "http://192.168.10.131:8008/";
        extraConfig = "client_max_body_size 300M;" +
          "proxy_set_header X-Forwarded-For $remote_addr;" +
          "proxy_set_header Host $host;" +
          "proxy_set_header X-Forwarded-Proto $scheme;";
      };
    };

    virtualHosts."element.XXXXXX.dynu.net" = {
      enableACME = true;
      addSSL = true;
      locations."/" = {
        proxyPass = "http://192.168.10.131:8009/";
        extraConfig = "proxy_set_header X-Forwarded-For $remote_addr;";
      };
    };

    virtualHosts."call.XXXXXX.dynu.net" = {
      enableACME = true;
      addSSL = true;
      locations."/" = {
        proxyPass = "http://192.168.10.131:8080/";
        extraConfig = "proxy_set_header X-Forwarded-For $remote_addr;";
      };
    };

    virtualHosts."livekit.XXXXXX.dynu.net" = {
      enableACME = true;
      addSSL = true;

      locations."/wss" = {
        proxyPass = "http://192.168.10.131:7881/";
#        proxyWebsockets = true;
        extraConfig = "proxy_http_version 1.1;" +
          "proxy_set_header X-Forwarded-For $remote_addr;" +
          "proxy_set_header Host $host;" +
          "proxy_set_header Connection \"upgrade\";" +
          "proxy_set_header Upgrade $http_upgrade;";
      };

      locations."/" = {
        proxyPass = "http://192.168.10.131:7880/";
#        proxyWebsockets = true;
        extraConfig = "proxy_http_version 1.1;" +
          "proxy_set_header X-Forwarded-For $remote_addr;" +
          "proxy_set_header Host $host;" +
          "proxy_set_header Connection \"upgrade\";" +
          "proxy_set_header Upgrade $http_upgrade;";
      };
    };

    virtualHosts."livekit-jwt.XXXXXX.dynu.net" = {
      enableACME = true;
      addSSL = true;
      locations."/" = {
        proxyPass = "http://192.168.10.131:7980/";
        extraConfig = "proxy_set_header X-Forwarded-For $remote_addr;";
      };
    };

    virtualHosts."turn.XXXXXX.dynu.net" = {
      enableACME = true;
      http2 = true;
      addSSL = true;
      locations."/" = {
        proxyPass = "http://192.168.10.131:5349/";
      };
    };

  };
}




[–] [email protected] 1 points 1 day ago* (last edited 1 day ago)

you only need to reboot Nix when something low level has changed. i honestly don't know where that line is drawn so i reboot quite a lot when i'm setting up a Nix server and then hardly reboot it at all from then on even with auto-updates running oh and if i make small changes to the services i just run sudo nixos-rebuild switch and don't reboot