ahembree / ansible-hms-docker

Ansible playbook for automated home media server setup
GNU General Public License v3.0
391 stars 47 forks source link

Internal or External access to services #3

Closed Ninja-FSE closed 1 year ago

Ninja-FSE commented 2 years ago

How can i specify in the default.yml on each container if i want to have internal or external access?

I know i can edit docker-compose.yml.j2 file and change "middlewares=internal-ipwhitelist" to my needs but how can i do this in the vars file with something like

For Internal access

nzbget: enabled: yes directory: yes traefik: yes expose: no

or for External access

nzbget: enabled: yes directory: yes traefik: yes expose: yes

ahembree commented 2 years ago

Just to clear some things up, you're wanting to expose containers (other than Overseerr) to the public internet, is that correct? Such as exposing your nzbget container to the public internet so that people can go to https://nzbget.<your domain> to login to your nzbget instance?

If so, I assume you're aware of the security risks and requirements of doing this? Such as needing to configure authentication on the exposed services manually (as by default they have no authentication).

Implementing per-container public internet exposure should be pretty straightforward, I just never thought about anyone needing to expose the other containers to the public tbh (as it's a bigger security impact).

If it'd be better, would an external-ipwhitelist variable work? This way you can control which IP's can access your publicly exposed containers, but this would require manual updates to the IP list if your users have dynamic IPs from their ISP. Just a thought, I can likely implement both shortly.

Ninja-FSE commented 2 years ago

Just to clear some things up, you're wanting to expose containers (other than Overseerr) to the public internet, is that correct? Such as exposing your nzbget container to the public internet so that people can go to https://nzbget. to login to your nzbget instance?

Yes sir :)

If so, I assume you're aware of the security risks and requirements of doing this? Such as needing to configure authentication on the exposed services manually (as by default they have no authentication).

Yes im aware of this and im about to try and include Authelia in your repo aswell :)

If it'd be better, would an external-ipwhitelist variable work?

This would work, but this also needs to update the docker-compose.yml aswell?

Super thanks for the really quick replay!

ahembree commented 2 years ago

Just created a new branch to test implementation, I have updated the code but have not yet verified it's working correctly

Link to changes if you're interested: https://github.com/ahembree/ansible-hms-docker/compare/master...per-container-public-exposure

ahembree commented 2 years ago

Also good call on the required updating of the docker-compose.yml whenever an external-ipwhitelist value would change. Definitely don't want to possibly cause an outage by updating that variable that would impact all containers in the compose, requiring them to restart. I didn't think about that ;)

Ninja-FSE commented 2 years ago

This works well, thanks for the help :)

Now i gonna try and intergrate Authelia into this aswell, if a service is exposed to the internet then it should be protected by authelia auth.

Ninja-FSE commented 2 years ago

One question, how does this work? im trying to understand this.

In defaults.yml i want to expose Sonarr, then i choose "yes"

then in docker-compose.yml file this line is called i think?

{% if not hms_docker_container_map['sonarr']['expose_to_public'] %}

This line is adding to the external ipwhitelist, but when i look at the routes in traefik dashboard, sonarr doesnt have any middleware at all, how can in statement add my own middlewares?

How does that line see if it should expose sonarr or not? Does it has something todo with "if not" statement?

ahembree commented 2 years ago

By changing the setting to expose_to_public: yes, this will cause the template to not add in the internal whitelist middleware to the compose file for that container, meaning there will be no IP restrictions set on who can access the container.

So this docker-compose.yml template line essentially says "if the container is not exposed to the public, add in the internal whitelist middleware. If it should be exposed, do not add the internal whitelist middleware".

Ninja-FSE commented 2 years ago

Okey. so to add my own middleware's i need to add something like

{% if hms_docker_container_map['portainer']['expose_to_public'] %} "traefik.http.routers.portainer-{{ project_name }}.middlewares=auth@authelia" another-middleware-here and-here

Hope you understand what im trying to ask :)

ahembree commented 2 years ago

Yeah I think I get the idea of what you're trying to do; it sounds like you're trying to add middlewares on a per-container basis which can be easily controlled by a variable, and still have the ability to specify other middlewares.

I tried to make this project as future-proof and scalable as possible, so here's a general idea of how I would do it.

(And I'm actually in the process of adding in authelia already if you want to wait for me to push that out)

But here's an example of how you could add a simple if statement per container to enable authelia or not:

...
  labels:
      - "traefik.label.here"
      - "another.traefik.label"
{% if hms_docker_container_map['portainer']['authelia'] %}
      - "traefik.http.routers.portainer-{{ project_name }}.middlewares=authelia@docker"
{% endif %}
      - "another.traefik.label"

This snippet means that within the hms_docker_container_map, if portainer has its authelia key set to yes, it will add in that line for the middleware.

This would also require you to add another "key" into the hms_docker_container_map per container with authelia: no (or yes to enable authelia for that container).

ahembree commented 2 years ago

I just pushed my basic authelia implementation to a new branch: https://github.com/ahembree/ansible-hms-docker/commit/f394b7fb4df315a5567ef5c0d17e4967d62de450

Try it out and let me know how it works. It should auto-generate a working config (for the most part). I've never used authelia before so this'll be fun to figure out.

ahembree commented 2 years ago

After looking at other options, I may switch it over to using authentik instead. It has better SAML and OAuth support, whereas authelia seems to be more of a http basic-auth layer on top of things. Like if you try to login to Portainer with authelia, you'll have 2 layers of authentication.

Ninja-FSE commented 2 years ago

I just pushed my basic authelia implementation to a new branch: f394b7f

Try it out and let me know how it works. It should auto-generate a working config (for the most part). I've never used authelia before so this'll be fun to figure out.

This is awesome, gonna try this at once!

After looking at other options, I may switch it over to using authentik instead. It has better SAML and OAuth support, whereas authelia seems to be more of a http basic-auth layer on top of things. Like if you try to login to Portainer with authelia, you'll have 2 layers of authentication.

Never played with Authentik, only visit their webpage, gonna read up about it :)

But first im gonna try your latest push :)

Ninja-FSE commented 2 years ago

Trying this out, and its not working i'm affraid.

TASK [hmsdocker : Ensure docker-compose.yml file.] *** task path: /home/xxx/ansible-hms-docker/roles/hmsdocker/tasks/main.yml:52

The full traceback is: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/ansible/template/init.py", line 1156, in do_template res = j2_concat(rf) File "