Files
kevinveenbirkenbachandClaude Opus 5.5 38902309f4 fix(web-app-pixelfed): send the OIDC token exchange through Tor on an onion issuer
On an onion deployment Pixelfed's server-side code-to-token exchange dials
the Keycloak .onion authority. libcurl refuses to resolve .onion names
(RFC 7686) before /etc/hosts or the SSO extra_hosts pin is consulted, so the
callback died with "cURL error 6: Not resolving .onion address" and both
OIDC login specs timed out (Pixelfed#0, compose, Tor, PR #869 run
37954856725).

Pixelfed builds its league/oauth2 GenericProvider without a proxy option,
so the proxy has to come from the environment. When the issuer is an onion,
env.j2 now sets http_proxy and https_proxy to the Tor socks5h endpoint,
with the object store host in no_proxy. Both Pixelfed services pin
host.docker.internal, the compose SOCKS endpoint, since the worker reads
the same env file. Clearnet deploys render no proxy.

Verified with a local compose deploy of variant 0 (SSO, seaweedfs, Tor): the
rendered token URL is an .onion authority, the env carries
socks5h://host.docker.internal:9050, and both pixelfed OIDC login specs pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 10:37:42 +02:00

163 lines
4.5 KiB
Django/Jinja

{% include 'roles/sys-svc-container/templates/env.j2' %}
APP_KEY={{ lookup('config', application_id, 'secrets.credentials.app_key')}}
# nocheck: env-file-literal-quoted-value
APP_NAME="{{ PIXELFED_TITEL }}"
APP_ENV={{ ENVIRONMENT | lower }}
APP_DEBUG={{MODE_DEBUG | string | lower }}
APP_URL={{ lookup('tls', application_id, 'url.base') }}
FORCE_HTTPS_URLS={{ lookup('tls', application_id, 'enabled') | string | lower }}
APP_DOMAIN={{ lookup('domain',application_id) }}
ADMIN_DOMAIN={{ lookup('domain',application_id) }}
SESSION_DOMAIN={{ lookup('domain',application_id) }}
SESSION_SECURE_COOKIE={{ lookup('tls', application_id, 'enabled') | string | lower }}
OPEN_REGISTRATION=false
ENFORCE_EMAIL_VERIFICATION=false
PF_MAX_USERS=1000
OAUTH_ENABLED=true
APP_TIMEZONE={{ HOST_TIMEZONE }}
APP_LOCALE={{ HOST_LL }}
LIMIT_ACCOUNT_SIZE=true
MAX_ACCOUNT_SIZE=1000000
MAX_PHOTO_SIZE=15000
MAX_AVATAR_SIZE=2000
MAX_CAPTION_LENGTH=500
MAX_BIO_LENGTH=125
MAX_NAME_LENGTH=30
MAX_ALBUM_LENGTH=4
IMAGE_QUALITY=80
PF_OPTIMIZE_IMAGES=true
PF_OPTIMIZE_VIDEOS=true
ADMIN_ENV_EDITOR=false
ACCOUNT_DELETION=true
ACCOUNT_DELETE_AFTER=false
MAX_LINKS_PER_POST=0
INSTANCE_PUBLIC_HASHTAGS=false
INSTANCE_PUBLIC_LOCAL_TIMELINE=false
STORIES_ENABLED=false
RESTRICTED_INSTANCE=false
{% set email = lookup('email', application_id) %}
{% if email.enabled | bool %}
MAIL_DRIVER=log
MAIL_HOST={{ email.host }}
MAIL_PORT={{ email.port }}
MAIL_FROM_ADDRESS={{ email['from'] }}
# nocheck: env-file-literal-quoted-value
MAIL_FROM_NAME="{{ service_provider.company.titel }} - Pixelfed"
MAIL_USERNAME={{ email.username }}
MAIL_PASSWORD={{ email.password | dotenv_quote }}
MAIL_ENCRYPTION={{ 'ssl' if email.start_tls else 'tls' }}
{% endif %}
DB_CONNECTION=mysql
DB_DATABASE={{ lookup('database', application_id, 'name') }}
DB_HOST={{ lookup('database', application_id, 'host') }}
DB_PASSWORD={{ lookup('database', application_id, 'password') | dotenv_quote }}
DB_PORT={{ lookup('database', application_id, 'port') }}
DB_USERNAME={{ lookup('database', application_id, 'username') }}
REDIS_CLIENT=phpredis
REDIS_SCHEME=tcp
REDIS_HOST={{ lookup('engine', 'redis', application_id, 'host') }}
REDIS_PASSWORD={{ lookup('engine', 'redis', application_id, 'password') | dotenv_quote }}
REDIS_PORT={{ lookup('engine', 'redis', application_id, 'port') }}
REDIS_DATABASE=0
HORIZON_PREFIX=horizon-
EXP_LC=false
EXP_REC=false
EXP_LOOPS=false
ACTIVITY_PUB=true
AP_REMOTE_FOLLOW=true
AP_SHAREDINBOX=true
AP_INBOX=true
AP_OUTBOX=true
ATOM_FEEDS=true
NODEINFO=true
WEBFINGER=true
{% if lookup('objstore', application_id, 'enabled') | bool %}
PF_ENABLE_CLOUD=true
FILESYSTEM_DRIVER=s3
DANGEROUSLY_SET_FILESYSTEM_DRIVER=s3
FILESYSTEM_CLOUD=s3
AWS_ACCESS_KEY_ID={{ lookup('objstore', application_id, 'access_key') }}
AWS_SECRET_ACCESS_KEY={{ lookup('objstore', application_id, 'secret_key') }}
AWS_DEFAULT_REGION={{ lookup('objstore', application_id, 'region') }}
AWS_BUCKET={{ lookup('objstore', application_id, 'bucket') }}
AWS_ENDPOINT={{ lookup('objstore', application_id, 'url') }}
AWS_URL={{ lookup('objstore', application_id, 'public_url') }}
AWS_USE_PATH_STYLE_ENDPOINT=true
{% else %}
FILESYSTEM_DRIVER=local
FILESYSTEM_CLOUD=s3
PF_ENABLE_CLOUD=false
{% endif %}
HORIZON_DARKMODE=false
PF_COSTAR_ENABLED=false
MEDIA_EXIF_DATABASE=false
LOG_CHANNEL=stderr
IMAGE_DRIVER=imagick
BROADCAST_DRIVER=log
CACHE_DRIVER=redis
RESTRICT_HTML_TYPES=true
QUEUE_DRIVER=redis
SESSION_DRIVER=redis
TRUST_PROXIES=*
ENABLE_CONFIG_CACHE=true
AUTORUN_ENABLED=true
AUTORUN_LARAVEL_MIGRATION=false
AUTORUN_LARAVEL_MIGRATION_ISOLATION=false
AUTORUN_LARAVEL_STORAGE_LINK=true
AUTORUN_LARAVEL_EVENT_CACHE=true
AUTORUN_LARAVEL_ROUTE_CACHE=true
AUTORUN_LARAVEL_VIEW_CACHE=true
AUTORUN_LARAVEL_CONFIG_CACHE=true
SSL_MODE=off
PHP_POST_MAX_SIZE=500M
PHP_UPLOAD_MAX_FILE_SIZE=500M
PHP_OPCACHE_ENABLE=1
{% if PIXELFED_OIDC_ENABLED | bool %}
PF_OIDC_ENABLED={{ PIXELFED_OIDC_ENABLED | string | lower }}
PF_OIDC_AUTHORIZE_URL={{ OIDC.CLIENT.AUTHORIZE_URL }}
PF_OIDC_TOKEN_URL={{ OIDC.CLIENT.TOKEN_URL }}
PF_OIDC_PROFILE_URL={{ OIDC.CLIENT.USER_INFO_URL }}
PF_OIDC_LOGOUT_URL={{OIDC.CLIENT.LOGOUT_URL}}
PF_OIDC_USERNAME_FIELD={{ OIDC.ATTRIBUTES.USERNAME }}
PF_OIDC_FIELD_ID={{ OIDC.ATTRIBUTES.USERNAME }}
PF_OIDC_CLIENT_SECRET={{ OIDC.CLIENT.SECRET | dotenv_quote }}
PF_OIDC_CLIENT_ID={{ OIDC.CLIENT.ID | dotenv_quote }}
# nocheck: env-file-literal-quoted-value
PF_OIDC_SCOPES="openid profile email"
{% if PIXELFED_OIDC_SOCKS_PROXY | length > 0 %}
http_proxy={{ PIXELFED_OIDC_SOCKS_PROXY }}
https_proxy={{ PIXELFED_OIDC_SOCKS_PROXY }}
no_proxy={{ PIXELFED_NO_PROXY }}
{% endif %}
{% endif %}