diff --git a/README.md b/README.md index a1f2220..a54248e 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,16 @@ those shared images. It exposes no ports, allows no incoming data, and has no API to exploit. +[Live demo](https://immich-demo.note.sx/share/ffSw63qnIYMtpmg0RNvOui0Dpio7BbxsObjvH8YZaobIjIAzl5n7zTX5d6EDHdOYEvo) + +### Why not simply put Immich behind a reverse proxy and only expose the `/share/` path to the public? + +To view a shared album in Immich, you need access to the `/api/` path. If you're sharing a gallery with the public, you need +to make that path public. Any existing or future vulnerabilities could compromise your Immich instance. + The ideal setup is to have Immich secured privately behind VPN or mTLS, and only allow public access to Immich Public Proxy. -[Live demo](https://immich-demo.note.sx/share/ffSw63qnIYMtpmg0RNvOui0Dpio7BbxsObjvH8YZaobIjIAzl5n7zTX5d6EDHdOYEvo) +Here is an example setup for [securing Immich behind mTLS](./docs/securing-immich-with-mtls.md). ## How to install with Docker @@ -64,10 +71,10 @@ https://your-proxy-url.com/share/ffSw63qnIYMtpmg0RNvOui0Dpio7BbxsObjvH8YZaobIjIA The part after `/share/` is Immich's shared link public ID (called the `key` [in the docs](https://immich.app/docs/api/get-my-shared-link)). -**Immich Public Proxy** takes that key and makes an API call to your Immich instance over your local network, to ask what +**Immich Public Proxy** takes that key and makes an API call to your Immich instance over your local network, to ask what photos or videos are shared in that share URL. -If it is a valid share URL, the proxy fetches just those assets via local API and returns them to the visitor as an +If it is a valid share URL, the proxy fetches just those assets via local API and returns them to the visitor as an individual image or gallery. If the shared link has expired or any of the assets have been put in the Immich trash, it will not return those. @@ -101,7 +108,9 @@ https://www.lightgalleryjs.com/docs/settings/ ## Feature requests You can [add feature requests here](https://github.com/alangrainger/immich-public-proxy/discussions/categories/feature-requests?discussions_q=is%3Aopen+category%3A%22Feature+Requests%22+sort%3Atop), -however my goal with this project is to keep it as lean as possible. +however my goal with this project is to keep it as lean as possible. Due to the sensitivity of data contained within Immich, I want anyone with a bit of coding knowledge to be able to read this codebase and fully understand everything it is doing. + +## D diff --git a/docs/securing-immich-with-mtls.md b/docs/securing-immich-with-mtls.md new file mode 100644 index 0000000..5268d64 --- /dev/null +++ b/docs/securing-immich-with-mtls.md @@ -0,0 +1,72 @@ +# Securing Immich with mTLS using Caddy + +## Caddy docker-compose.yml + +```yaml +version: "3.7" + +services: + caddy: + build: + context: . + dockerfile: Dockerfile + restart: unless-stopped + cap_add: + - NET_ADMIN + ports: + - "6443:443" + - "6443:443/udp" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:Z + - ./site:/srv:Z + - ./data:/data:Z + - ./config:/config:Z +``` + +## Authenticating with mutual TLS + +### Generate your client certificate + +This is a basic way to generate a certificate for a user. If it's only you using your own homelab, then you'll just need to make one certificate. + +This certificate will last for ~10 years (although of course you can revoke it at any time by deleting it from Caddy's key store). + +```bash +#!/bin/bash + +mkdir -p certs + +# Generate CA certificates +openssl genrsa -out certs/client-ca.key 4096 +openssl req -new -x509 -nodes -days 3600 -key certs/client-ca.key -out certs/client-ca.crt + +# Generate a certificate signing request +openssl req -newkey rsa:4096 -nodes -keyout certs/client.key -out certs/client.req + +# Have the CA sign the certificate requests and output the certificates. +openssl x509 -req -in certs/client.req -days 3600 -CA certs/client-ca.crt -CAkey certs/client-ca.key -set_serial 01 -out certs/client.crt + +echo +echo "Please enter a STRONG password. Many clients *require* a password for you to be able to import the certificate, and you want to protect it." +echo + +# Convert the cerificate to PKCS12 format (for import into browser) +openssl pkcs12 -export -out certs/client.pfx -inkey certs/client.key -in certs/client.crt + +# Clean up +rm certs/client.req +``` + +## Configure Caddyfile + +```Caddyfile +https://immich.mydomain.com { + tls { + client_auth { + mode require_and_verify + trusted_ca_cert_file /data/client_certs/client.crt + } + } + reverse_proxy internal_server.lan:2283 +} +```