Skip to content

Instantly share code, notes, and snippets.

@JamesCullum
Last active March 28, 2024 04:30
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamesCullum/6604e504318dd326a507108f59ca7dcd to your computer and use it in GitHub Desktop.
Save JamesCullum/6604e504318dd326a507108f59ca7dcd to your computer and use it in GitHub Desktop.
docker-compose.yml for immich with WAF, DDoS protection, image resizing and without port forwarding

Setup Immich via Docker Compose with WAF, CDN, DDoS protection, no port forwarding and automated image resizing

In this guide, we are using the docker compose setup that is recommended by the Immich team. Once everything is configured and running in your local network, we can expand on it.

The first recommended step is to use Cloudflare Tunnel to make your local instance globally available. This is free and you benefit from the native DDoS protection, WAF and CDN from Cloudflare. The cloudflared daemon basically makes an outgoing connection to Cloudflare and makes the designed interfaces available on the internet, without granting access to undesired parts of the network.

Start off by creating a Cloudflare account, going into the "Zero Trust" portion of the account and add a new tunnel. Give it a name and choose a domain that you want your instance to be available on. You can use the "Access" components (SSO/VPN) to lock down the access, if you want. Once you have to choose a local agent, select "Docker" and copy the token from the instructions. Add the following command into your docker-compose.yml and add your valid tunnel token.

  cloudflared:
    container_name: cloudflared
    image: cloudflare/cloudflared:latest
    depends_on:
      - immich-server
    restart: always
    command: 'tunnel --no-autoupdate run --token YOUR-TOKEN'

Use docker compose to start this container, the UI should show your node being online now. Now switch to "Public hostname" , add the desires subdomain for your immich instance, leave path empty and for the service you configure HTTP with immich_proxy:8080 as destination. Once saved, your cloudflared daemon will automatically update and your immich is now available on the internet.

If you would like your pictures to be automatically resized - a feature which the Immich maintainers have declined - you can add the following code to your docker-compose.yml. Feel free to change the dimensions you are looking for.

  upload-proxy:
    container_name: upload_proxy
    image: ghcr.io/jamescullum/multipart-upload-proxy:main
    environment:
      - IMG_MAX_WIDTH=1920
      - IMG_MAX_HEIGHT=1080
      - FORWARD_DESTINATION=http://immich-server:3001/api/asset/upload
      - FILE_UPLOAD_FIELD=assetData
      - LISTEN_PATH=/api/asset/upload
    restart: always

You need to route uploads to this container now, which is easy to do via Cloudflare tunnel. Create a new public hostname, use api/asset/upload as path and direct it via HTTP to upload_proxy:6743. Submit and move this public hostname above the previous one.

Screenshot immich with cloudflare tunnel

Now all file uploads will be proxied and images automatically resized before being uploaded to Immich.

@telgareith
Copy link

telgareith commented Dec 17, 2023

it's not even a "threat scenario" - It's about doing things correctly, and not teaching people bad habits. You use Environment Variables in your own container...

Just need to change cloudflared to:

  cloudflared:
    container_name: cloudflared
    image: cloudflare/cloudflared:latest
    depends_on:
      - immich-server
    environment:
      - TUNNEL_TOKEN = YOUR-TOKEN
    restart: always
    command: 'tunnel --no-autoupdate run'

And I said "anyone/thing that can list processes," for a reason: non admin users and logging. OOM kill, container start, container stop, process fault, too many to name... All result in TUNNEL_TOKEN in the logs.

Finally: Storing compose files somewhere every user on the machine can access them is bad practice.

@Ranger-NF
Copy link

Ranger-NF commented Dec 19, 2023

Just a quick question, how could I automatically resize the pictures I upload over mobile app without using cloudflare tunnel? (ie, connecting over local network)
Does simply adding the following to docker-compose file make that work?

    upload-proxy:
    container_name: upload_proxy
    image: ghcr.io/jamescullum/multipart-upload-proxy:main
    environment:
      - IMG_MAX_WIDTH=1920
      - IMG_MAX_HEIGHT=1080
      - FORWARD_DESTINATION=http://immich-server:3001/api/asset/upload
      - FILE_UPLOAD_FIELD=assetData
      - LISTEN_PATH=/api/asset/upload
    restart: always

NB: I'm still in my early phase of using docker 😅

@JamesCullum
Copy link
Author

@telgareith Thank you for providing an alternative version for the Tunnel using an environment variable.

@Ranger-NF Sadly not. You need all requests to go to Immich with the exception of the file upload API, which should go to the resizing proxy. If you really don't want to use the Cloudflare tunnel (really try to give it a shot - it's free and has many great benefits), then you will need another container as reverse proxy in front of your application.

@Ranger-NF
Copy link

Ranger-NF commented Dec 22, 2023

@telgareith Thank you for providing an alternative version for the Tunnel using an environment variable.

@Ranger-NF Sadly not. You need all requests to go to Immich with the exception of the file upload API, which should go to the resizing proxy. If you really don't want to use the Cloudflare tunnel (really try to give it a shot - it's free and has many great benefits), then you will need another container as reverse proxy in front of your application.

I would love to use cloudflare tunnels, but I don't own any domain. So that option is out of the question...

Let me know if there are any solutions for this!

@JamesCullum
Copy link
Author

Hmm so you only want Immich available via home wifi and static IP? A DynDNS provider might help you out and solve two problems at once.

Cloudflare tunnel does not require a domain and will generate you a free one: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/

@tehniemer
Copy link

The use of multipart in the image name gives me hope that this does chunked uploads to get around Cloudflare's 100mb limit, is that the case or am I suffering from wishful thinking?

@JamesCullum
Copy link
Author

JamesCullum commented Jan 21, 2024

Multipart is a subcomponent of the HTTP form protocol to allow file uploads - the proxy does not circumvent any limitations. I did not find the limitation you mentioned in tunnel documentation.

@tehniemer
Copy link

OK, thanks for the info, I'm using Traefik2 as my reverse proxy and Cloudflare as my DNS provider, and Cloudflare has the limitation.

@JamesCullum
Copy link
Author

JamesCullum commented Jan 23, 2024

Your DNS provider has nothing to do with filesize limits. Check your reverse proxy or client for that.

I didn't find such a limitation for the Cloudflare tunnel either, so it looks like your problem is somewhere else.

@tehniemer
Copy link

tehniemer commented Jan 23, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment