diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..37429b0 --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +# OAuth2 Proxy Configuration +# Copy this file to .env and fill in your values + +# GitHub OAuth credentials +# Get these from: GitHub → Settings → Developer settings → OAuth Apps +GITHUB_CLIENT_ID=your-github-client-id-here +GITHUB_CLIENT_SECRET=your-github-client-secret-here + +# Cookie secret - generate with: openssl rand -base64 24 +OAUTH2_PROXY_COOKIE_SECRET=your-cookie-secret-here + +# Example (do not use these): +# GITHUB_CLIENT_ID=Iv1.abc123xyz789 +# GITHUB_CLIENT_SECRET=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0 +# OAUTH2_PROXY_COOKIE_SECRET=XOtjj+hRLbjkdzz1BAchBcUd/hR6WSt0 diff --git a/.gitignore b/.gitignore index 6cb7347..54a7618 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ -filebrowser/filebrowser.db -filebrowser/tailscale-state/** +.env +llama/tailscale-state/ comfyui/tailscale-state/** +filebrowser/tailscale-state/** +filebrowser/filebrowser.db llama/tailscale-state/** +*.log +.DS_Store diff --git a/docker-compose.yml b/docker-compose.yml index 0fdd33e..00577d9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: image: tailscale/tailscale:latest hostname: comfyui environment: - - TS_AUTHKEY=tskey-auth-kNm64Dbcts11CNTRL-4eLQjm2pQYCLdy285gNaYCFDF1KTjP71 + - TS_AUTHKEY=$TS_AUTHKEY - TS_STATE_DIR=/var/lib/tailscale - TS_SERVE_CONFIG=/config/ts_serve.json - TS_USERSPACE=false @@ -33,7 +33,7 @@ services: image: tailscale/tailscale:latest hostname: filebrowser environment: - - TS_AUTHKEY=tskey-auth-kNm64Dbcts11CNTRL-4eLQjm2pQYCLdy285gNaYCFDF1KTjP71 + - TS_AUTHKEY=$TS_AUTHKEY - TS_STATE_DIR=/var/lib/tailscale - TS_SERVE_CONFIG=/config/ts_serve.json - TS_USERSPACE=false @@ -73,7 +73,7 @@ services: image: tailscale/tailscale:latest hostname: llama environment: - - TS_AUTHKEY=tskey-auth-kNm64Dbcts11CNTRL-4eLQjm2pQYCLdy285gNaYCFDF1KTjP71 + - TS_AUTHKEY=$TS_AUTHKEY - TS_STATE_DIR=/var/lib/tailscale - TS_SERVE_CONFIG=/config/ts_serve.json - TS_USERSPACE=false @@ -87,12 +87,45 @@ services: - net_raw restart: unless-stopped + llama_oauth2_proxy: + image: quay.io/oauth2-proxy/oauth2-proxy:latest + container_name: llama_oauth2_proxy + depends_on: + - llama_tailscale + environment: + - OAUTH2_PROXY_PROVIDER=github + - OAUTH2_PROXY_CLIENT_ID=${GITHUB_CLIENT_ID} + - OAUTH2_PROXY_CLIENT_SECRET=${GITHUB_CLIENT_SECRET} + - OAUTH2_PROXY_COOKIE_SECRET=/kGl9ruL8N01Yx5Mj9kVFfuyTehhl3/5 + - OAUTH2_PROXY_COOKIE_NAME=llama_session + - OAUTH2_PROXY_COOKIE_DOMAINS=llama.story-basking.ts.net + - OAUTH2_PROXY_COOKIE_EXPIRE=168h0m0s + - OAUTH2_PROXY_COOKIE_REFRESH=60m + - OAUTH2_PROXY_COOKIE_SECURE=true + - OAUTH2_PROXY_COOKIE_HTTPONLY=true + - OAUTH2_PROXY_COOKIE_SAMESITE=lax + - OAUTH2_PROXY_REDIRECT_URL=https://llama.story-basking.ts.net/oauth2/callback + - OAUTH2_PROXY_EMAIL_DOMAINS=* + - OAUTH2_PROXY_UPSTREAMS=http://workstation:5082 + - OAUTH2_PROXY_HTTP_ADDRESS=0.0.0.0:4180 + - OAUTH2_PROXY_REVERSE_PROXY=true + - OAUTH2_PROXY_PASS_AUTHORIZATION_HEADER=true + - OAUTH2_PROXY_PASS_ACCESS_TOKEN=true + - OAUTH2_PROXY_SET_XAUTHREQUEST=true + - OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true + - OAUTH2_PROXY_SESSION_STORE_TYPE=cookie + - OAUTH2_PROXY_STANDARD_LOGGING=true + - OAUTH2_PROXY_AUTH_LOGGING=true + - OAUTH2_PROXY_REQUEST_LOGGING=true + restart: unless-stopped + network_mode: service:llama_tailscale + llama_nginx: image: nginx:latest depends_on: - llama_tailscale + - llama_oauth2_proxy restart: unless-stopped volumes: - ./llama/nginx.conf:/etc/nginx/nginx.conf:ro - - ./.htpasswd:/etc/nginx/.htpasswd:ro network_mode: service:llama_tailscale diff --git a/generate-cookie-secret.sh b/generate-cookie-secret.sh new file mode 100755 index 0000000..f6d2d95 --- /dev/null +++ b/generate-cookie-secret.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Generate a secure cookie secret for oauth2-proxy +# Cookie secret must be 16, 24, or 32 bytes when base64-decoded + +set -e + +echo "Generating OAuth2 Proxy cookie secret..." +echo "" + +# Generate exactly 24 random bytes (encodes to 32 base64 chars) +COOKIE_SECRET=$(openssl rand -base64 24 | tr -d '\n') + +echo "Generated Cookie Secret:" +echo "$COOKIE_SECRET" +echo "" + +# Update docker-compose.yml if it exists +if [ -f "docker-compose.yml" ]; then + echo "Updating docker-compose.yml..." + sed -i "s|OAUTH2_PROXY_COOKIE_SECRET=.*|OAUTH2_PROXY_COOKIE_SECRET=$COOKIE_SECRET|" docker-compose.yml + echo "Updated OAUTH2_PROXY_COOKIE_SECRET in docker-compose.yml" +else + echo "docker-compose.yml not found. Add this to your environment:" + echo " OAUTH2_PROXY_COOKIE_SECRET=$COOKIE_SECRET" +fi + +echo "" +echo "Restart the oauth2-proxy container to apply:" +echo " docker-compose restart llama_oauth2_proxy" diff --git a/llama/nginx.conf b/llama/nginx.conf index 3858163..4b815c3 100644 --- a/llama/nginx.conf +++ b/llama/nginx.conf @@ -20,21 +20,36 @@ http { text/plain text/xml; + # CORS headers for OAuth redirects + map $http_origin $cors_origin { + default ""; + "https://llama.story-basking.ts.net" $http_origin; + } + server { listen 80; server_name _; - auth_basic "Restricted Access"; - auth_basic_user_file /etc/nginx/.htpasswd; - client_max_body_size 100M; location / { - proxy_pass http://workstation:5082; + # Add CORS headers to all responses + add_header Access-Control-Allow-Origin $cors_origin always; + add_header Access-Control-Allow-Credentials true always; + add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; + add_header Access-Control-Allow-Headers "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" always; + + # Handle preflight requests + if ($request_method = OPTIONS) { + return 204; + } + + proxy_pass http://llama_oauth2_proxy:4180; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Auth-Request-Redirect $request_uri; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; @@ -43,6 +58,10 @@ http { proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; + + # Important: Pass cookies properly + proxy_pass_header Set-Cookie; + proxy_cookie_domain localhost llama.story-basking.ts.net; } } } diff --git a/llama/oauth2-proxy.cfg b/llama/oauth2-proxy.cfg new file mode 100644 index 0000000..a525c9c --- /dev/null +++ b/llama/oauth2-proxy.cfg @@ -0,0 +1,50 @@ +## OAuth2 Proxy Configuration +## Using GitHub as the identity provider + +# Provider settings +provider = "github" + +# Get these from GitHub Settings → Developer settings → OAuth Apps +client_id = "${GITHUB_CLIENT_ID}" +client_secret = "${GITHUB_CLIENT_SECRET}" + +# Cookie settings +cookie_name = "llama_session" +cookie_secret = "${OAUTH2_PROXY_COOKIE_SECRET}" +cookie_domains = [".story-basking.ts.net"] +cookie_expire = "168h0m0s" +cookie_refresh = "60m" +cookie_secure = true +cookie_httponly = true +cookie_samesite = "none" + +# Redirect URL - must match GitHub OAuth settings +redirect_url = "https://llama.story-basking.ts.net/oauth2/callback" + +# GitHub specific - restrict to specific orgs/users (optional) +# github_org = "your-org" +# github_team = "your-team" +github_user = "brycecovert" + +# Upstream - your llama service +upstreams = [ "http://workstation:5082" ] + +# Server settings +http_address = "0.0.0.0:4180" +reverse_proxy = true + +# Pass user info to upstream +pass_authorization_header = true +pass_access_token = true +set_xauthrequest = true + +# Skip the provider selection button +skip_provider_button = true + +# Session storage +session_store_type = "cookie" + +# Logging +standard_logging = true +auth_logging = true +request_logging = true diff --git a/llama/ts_serve.json b/llama/ts_serve.json index 3984161..9fd77a9 100644 --- a/llama/ts_serve.json +++ b/llama/ts_serve.json @@ -8,7 +8,7 @@ "llama.story-basking.ts.net:443": { "Handlers": { "/": { - "Proxy": "http://127.0.0.1:80" + "Proxy": "http://127.0.0.1:4180" } } }