this post was submitted on 05 Jul 2023
9 points (76.5% liked)

Selfhosted

39239 readers
477 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 1 year ago
MODERATORS
 

There have been a few Reddit, Lemmy and Youtube posts over the past week or so about Nginx Proxy Manager and their shortfalls, mostly towards CVEs and other security issues.

The problem is that unlike Traefik, NGINX Proxy Manager is actually easy to use. And before you recommend Caddy, that also has no GUI.

What do you use, if you have stuff exposed to the outside?

top 32 comments
sorted by: hot top controversial new old
[–] Zeku@feddit.de 9 points 1 year ago* (last edited 1 year ago) (1 children)

Traefik. Once you set it up (which granted can take a few hours if you're new) its as easy as adding 4 lines of code to your compose file to add a new service. I started with NPM but I don't regret switching to Traefik at all.

I heard caddy is cool, too.

[–] dustojnikhummer@lemmy.world 2 points 1 year ago

With some help from this thread I think I got Traefik working! And from now on I can just add another dynamic.toml/yml file with a new srevice. Thanks!

[–] oranki@sopuli.xyz 5 points 1 year ago

Plain NGINX has served me well.

[–] thews@lemmy.oldtr.uk 4 points 1 year ago (1 children)

If you are going to programmatically manage the reverse proxy, traefik is much better than NPM.

You can make NPM's manager only accessible internally or from a certain IP to reduce your attack surface. I use both.

[–] dustojnikhummer@lemmy.world 2 points 1 year ago (1 children)

Obviously I'm not going to expose the NPM control panel to the outside, I'm not insane. Tbf I really only expose Jellyfin because other family members use it, otherwise I would be VPNing in all the way.

[–] thews@lemmy.oldtr.uk 2 points 1 year ago

I didn't figure so, just wanted to say that because it's the more vulnerable attack surface. I hope overlay networks catch on in a bigger way, I share some of my resources with zerotier without having stuff directly exposed.

[–] partizan@lemmy.fmhy.ml 2 points 1 year ago

I use a plain nginx and certbot. Was trying to use traefik, but it lacked some capabilities for serving static content and some specific functions...

I however use traefik in a docker swarm as an ingress and its quite good at that position if you dont need special capabilities like running scripts and serving partially static stuff.

[–] terribleplan@lemmy.nrd.li 2 points 1 year ago (1 children)

Traefik. It has a GUI that I can use to see things, and (depending on your setup) you define the routes and stuff as part of your container definitions, minimal extra work required, makes setup and teardown a breeze. It is also nice that you can use it in all sorts of places, I have used it as Kubernetes ingress and as the thing that routed traffic to a Nomad cluster.

I went from Apache to Nginx (manually configured, including ACME) to Traefik over the course of the past ~10 years. I tried Caddy when I was making the switch to Traefik and found it very annoying to use, too much magic in the wrong places. I have never actually used NPM, as it doesn't seem useful for what I want...

Anyway, with traefik you can write your services in docker compose like this, and traefik will just pick them up and do the right thing:

version: "3"
services:
  foo-example-com:
    image: nginx:1.24-alpine
    volumes: ['./html:/usr/share/nginx/html:ro']
    labels:
      'traefik.http.routers.foo-example-com.rule': Host(`foo.example.com`)
    restart: unless-stopped
    networks:
      - traefik
networks:
  traefik:
    name: traefik-expose-network
    external: true

It will just work most of the time, though sometimes you'll have to specify 'traefik.http.services.foo-example-com.loadbalancer.server.port': whatever or other labels according to the traefik docs if you want specific behaviors or middleware or whatever.

And your deployment of traefik would look something like this:

version: '3'
services:
  traefik:
    image: traefik:v2
    command: >-
      --accesslog=true
      --api=true
      --api.dashboard=true
      --api.debug=true
      --certificatesresolvers.le.acme.dnschallenge.provider=provider
      --certificatesresolvers.le.acme.storage=acme.json
      [ ... other ACME stuff ... ]
      --entrypoints.http.address=:80
      --entrypoints.http.http.redirections.entrypoint.to=https
      --entrypoints.http.http.redirections.entrypoint.scheme=https
      --entrypoints.https.address=:443
      --entrypoints.https.http.tls.certresolver=le
      --entrypoints.https.http.tls.domains[0].main=example.com
      --entrypoints.https.http.tls.domains[0].sans=*.example.com
      --entrypoints.https.http.tls=true
      --global.checknewversion=false
      --global.sendanonymoususage=false
      --hub=false
      --log.level=DEBUG
      --pilot.dashboard=false
      --providers.docker=true
    environment:
      [ ... stuff for your ACME provider ... ]
    ports:
      # this assumes you just want to do simple port forwarding or something
      - 80:80
      - 443:443
      # - 8080:8080 uncomment if you want to hit port 8080 of this machine for the traefik gui
    working_dir: /data
    volumes:
      - ./persist:/data
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - traefik
    restart: unless-stopped
networks:
  traefik:
    name: traefik-expose-network
    external: true

Note that you'd have to create the traefik-expose-network manually for this to work, as that is how traefik will talk to your different services. You can get even fancier and set it up to expose your sites by default and auto-detect what to call them based on container name and stuff, but that is beyond the scope of a comment like this.

Technically my setup is a little more complex to allow for services on many different machines (so I don't use the built-in docker provider), and to route everything from the internet using frp using proxy protocol so I don't expose my home IP... I think this illustrates the point well regardless.

[–] dustojnikhummer@lemmy.world 1 points 1 year ago* (last edited 1 year ago) (1 children)

Well, it works just fine for Docker containers, but trying to point it at other services is what is making my head hurt. With NPM it is literally "this IP at this port with this certificate = https://service.domain.tld"


version: "3.3"

services:
  traefik:
    image: "traefik:latest"
    container_name: "traefik"
    networks:
      - npm_bridge
    command:
      #- "--log.level=DEBUG"
      - "--providers.docker.exposedbydefault=false"
    ports:
      - "443:443"
      - "80:80"
      - "8180:8080"
    volumes:
      - "/docker/containers/traefik/letsencrypt:/letsencrypt"
      - "/docker/containers/traefik/:/etc/traefik"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
  npm_bridge:
    external: true


traefik.toml

[entryPoints]
  [entryPoints.web]
    address = ":80"
    #[entryPoints.web.http.redirections.entryPoint]
      #to = "websecure"
      #scheme = "https"

  [entryPoints.websecure]
    address = ":443"

[api]
  dashboard = true
  insecure = true

[certificatesResolvers.letsencrypt.acme]
  email = "[redacted]"
  storage = "/letsencrypt/acme.json"
  #caserver = "https://acme-staging-v02.api.letsencrypt.org/directory"
  caserver = "https://acme-v02.api.letsencrypt.org/directory"
  [certificatesResolvers.letsencrypt.acme.tlsChallenge]

[providers]
  [providers.docker]
    watch = true
    network = "npm_bridge"
  [providers.file]
    directory = "/etc/traefik/dynamic"
    watch = true

traefik_dynamic.toml

[tls.options]
  [tls.options.default]
    sniStrict = true
    minVersion = "VersionTLS12"
    curvePreferences = [
      "secp521r1",
      "secp384r1"
    ]
    cipherSuites = [
      "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
      "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
      "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
    ]
    [tls.options.mintls13]
      minVersion = "VersionTLS13"

[http]
  [http.routers]
    [http.routers.jellyfin]
      rule = "Host(`jellyfin.[redacted].com`) && PathPrefix(`/`)"
      service = "jellyfin"
      entrypoints = "websecure"
        [http.routers.librespeed]
      rule = "Host(`librespeed.[redacted].com`) && PathPrefix(`/`)"
      service = "librespeed"
      entrypoints = "websecure"

  [http.services]
    [http.services.jellyfin.loadBalancer]
      [[http.services.jellyfin.loadBalancer.servers]]
        url = "http://10.0.1.201:8096"
    [http.services.librespeed.loadBalancer]
      [[http.services.librespeed.loadBalancer.servers]]
        url = "http://10.0.1.201:10016"

This setup sadly ends up with ERR_SSL_UNRECOGNIZED_NAME_ALERT for both services
These URLs are NOT  proxied through Cloudflare. I'm trying to move from Truecharts + Traefik into manual docker + traefik
[–] terribleplan@lemmy.nrd.li 1 points 1 year ago* (last edited 1 year ago) (1 children)

Is traefik successfully getting the cert via LE? It sounds like for one reason or another it is still using the built-in/default cert for those services. You can check the traefik log's LEGO lines, and/or look at your /letsencrypt/acme.json.

In my example I specified entrypoints.https.http.tls.domains, but I think that is only necessary when you're doing wildcard domains with a DNS solver.

edit: You may need to use the file provider rather than trying to specify stuff in the main config toml... traefik differentiates from "static" config that it has to know at boot time and can't change and "dynamic" config like routers and stuff.

[–] dustojnikhummer@lemmy.world 1 points 1 year ago (1 children)

I am using a dynamic file, traefik_dynamic.toml

And it seems like I'm not getting certificates, acme.json doesn't have those two services in my dynamic config, ie jellyfin and librespeed

[–] terribleplan@lemmy.nrd.li 1 points 1 year ago (1 children)

Your logs (at debug level at least, which is where I keep my server, haha) should have entries something along the lines of:

  • Receiving configuration from the file provider
  • What routers and services it sets up based on the configuration
  • Whether certificate generation is needed for the routers
  • What happens when LEGO tries to generate the certificate (created account, got challenge, passed/failed challenge, got cert, etc)
[–] dustojnikhummer@lemmy.world 1 points 1 year ago (1 children)

The only thing Portainer gives me is weirdly

time="2023-07-05T20:42:26Z" level=info msg="Configuration loaded from file: /etc/traefik/traefik.toml"

And syntax errors in my dynamic.toml file, but nothing about routers, services or certificates

I can see those services and routers in the traefik dashboard though

[–] terribleplan@lemmy.nrd.li 1 points 1 year ago (1 children)

I am pretty sure what I described is only when --log.level=DEBUG or

[log]
  level = "DEBUG"

The syntax errors are weird/concerning if it says there are errors but it still seems to load the config anyway (based on you seeing them in the dashboard).

Back when I used the file provider I pointed it at a directory and put every router/service in its own file with that volume'd in to e.g. /traefik-conf. That's probably more just advice than being your problem though.

[–] dustojnikhummer@lemmy.world 1 points 1 year ago

I did try having jellyfin.toml and librespeed.toml but thought that isn't possible. If it is I would def prefer to go that way.

The syntax errors are weird/concerning

I often save when editing files, that's why it's popping up there

Enabled log.level debug but still nothing

[–] chiisana@lemmy.chiisana.net 2 points 1 year ago (1 children)

Traefik just need container labels. Most of the time it’s only 4 labels for the container you want to expose. Copy to a self hosted wiki and you’re good to go.

[–] dustojnikhummer@lemmy.world 1 points 1 year ago (1 children)

That is the easy part. What I haven't been able to get working is services outside of docker, ie on other servers

[–] ironhydroxide@partizle.com 1 points 1 year ago* (last edited 1 year ago) (1 children)

Setup rules that forward to an IP:port I used a guide on smarthomebeginner initially. I'll try and find it found it.

Go here https://www.smarthomebeginner.com/traefik-docker-compose-guide-2022/

And scroll till the section. "Adding non-docker or external apps behind Traefik"

[–] dustojnikhummer@lemmy.world 3 points 1 year ago (1 children)

That seems to have done it!

http:
  routers:
    jellyfin-rtr:
      rule: "Host(`[redacted].com`)"
      entryPoints:
        - websecure
      service: jellyfin-svc
      tls:
        certResolver: letsencrypt
  services:
    jellyfin-svc:
      loadBalancer:
        servers:
          - url: "http://[]redacted]:8096" 
[–] chiisana@lemmy.chiisana.net 2 points 1 year ago (1 children)

🎉

Glad you’re able to get this working and welcome to Traefik !

[–] dustojnikhummer@lemmy.world 1 points 1 year ago

Glad to be here. I have been using Traefik for well over a year, but through TrueCharts, glad to have done this on my own

[–] frankblack@lemmy.world 1 points 1 year ago (1 children)

Traefik has a GUI you can installed. I use Cloudflare ZT

[–] dustojnikhummer@lemmy.world 2 points 1 year ago

GUI that just tells you how it is configured, you can't configure anything there

[–] clb92@kbin.social 1 points 1 year ago* (last edited 1 year ago)

I vote for Caddy anyway

[–] qazwsxedcrfv000@lemmy.unknownsys.com 1 points 1 year ago (1 children)

Okay I use plain Nginx at home and at work mostly. Caddy (or its underlying Go runtime) has some performance regressions with HTTP/2 back then. Not sure if it has been fixed or not. Traefik is more container (docker/kubernete) affinitive imo, though I know it can be configured to function just like Nginx and Caddy.

P.S. I stopped for a second thinking what NPM you are referring to.... (Isn't that Node Package Manager lol)

[–] dustojnikhummer@lemmy.world 2 points 1 year ago (1 children)

Yes the NPM (Node.js vs NGINX Proxy Manager) is unfortunate, but why would I be comparing package manager to a reverse proxy ey?

Yeah I quickly realize that but it has taken a second still haha.

[–] 7egend@lemmy.ml 1 points 1 year ago (1 children)

I previously used NPM, it was easy to use and simple, but more robust stuff had to be done in the config area. I ended up having to edit configs more often than not in the end, so I switched to Traefik so now I just drop some extra blocks of text directly in my compose files and it just handles it.

[–] dustojnikhummer@lemmy.world 3 points 1 year ago

I guess once I get Traefik to work it might just click (and I can move my configs into the future). I just wish Traefik had at least a config generator UI similar to NPM. I just want "this IP on this port with this certificate = https://url.tld, if you get what I mean

[–] alvaro@social.graves.cl 0 points 1 year ago (1 children)

@dustojnikhummer@lemmy.world I'm using SWAG on my VPS and I'm seriously thinking of using it for my home server as well (using NPM for now)

[–] Protegee9850@lemmy.world 0 points 1 year ago

Vote for NPM

load more comments
view more: next ›