feat: use Phoenix config for theme injection (cleaner approach)
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
services:
|
services:
|
||||||
asciinema_backend:
|
asciinema:
|
||||||
image: ${ASCIINEMA_IMAGE:-ghcr.io/asciinema/asciinema-server:latest}
|
image: ${ASCIINEMA_IMAGE:-ghcr.io/asciinema/asciinema-server:latest}
|
||||||
container_name: ${ASCIINEMA_COMPOSE_PROJECT_NAME}_backend
|
container_name: ${ASCIINEMA_COMPOSE_PROJECT_NAME}_app
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- compose_network
|
- compose_network
|
||||||
volumes:
|
volumes:
|
||||||
- asciinema_data:/var/opt/asciinema
|
- asciinema_data:/var/opt/asciinema
|
||||||
- ./custom.exs:/opt/app/etc/custom.exs:ro
|
- ./custom.exs:/opt/app/etc/custom.exs:ro
|
||||||
|
- ./theme:/opt/app/priv/static/theme:ro
|
||||||
environment:
|
environment:
|
||||||
SECRET_KEY_BASE: ${ASCIINEMA_SECRET_KEY}
|
SECRET_KEY_BASE: ${ASCIINEMA_SECRET_KEY}
|
||||||
URL_HOST: ${ASCIINEMA_TRAEFIK_HOST}
|
URL_HOST: ${ASCIINEMA_TRAEFIK_HOST}
|
||||||
@@ -19,18 +20,6 @@ services:
|
|||||||
SMTP_FROM_ADDRESS: ${EMAIL_FROM}
|
SMTP_FROM_ADDRESS: ${EMAIL_FROM}
|
||||||
SIGN_UP_DISABLED: ${ASCIINEMA_SIGN_UP_DISABLED:-false}
|
SIGN_UP_DISABLED: ${ASCIINEMA_SIGN_UP_DISABLED:-false}
|
||||||
DEFAULT_AVATAR: gravatar
|
DEFAULT_AVATAR: gravatar
|
||||||
|
|
||||||
asciinema:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: ${ASCIINEMA_COMPOSE_PROJECT_NAME}_app
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- compose_network
|
|
||||||
volumes:
|
|
||||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
|
||||||
- ./theme:/theme:ro
|
|
||||||
depends_on:
|
|
||||||
- asciinema_backend
|
|
||||||
labels:
|
labels:
|
||||||
- 'traefik.enable=${ASCIINEMA_TRAEFIK_ENABLED}'
|
- 'traefik.enable=${ASCIINEMA_TRAEFIK_ENABLED}'
|
||||||
# Main web interface - HTTP to HTTPS redirect
|
# Main web interface - HTTP to HTTPS redirect
|
||||||
@@ -46,7 +35,7 @@ services:
|
|||||||
- 'traefik.http.middlewares.${ASCIINEMA_COMPOSE_PROJECT_NAME}-compress.compress=true'
|
- 'traefik.http.middlewares.${ASCIINEMA_COMPOSE_PROJECT_NAME}-compress.compress=true'
|
||||||
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-web-secure.middlewares=${ASCIINEMA_COMPOSE_PROJECT_NAME}-compress,security-headers@file'
|
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-web-secure.middlewares=${ASCIINEMA_COMPOSE_PROJECT_NAME}-compress,security-headers@file'
|
||||||
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-web-secure.service=${ASCIINEMA_COMPOSE_PROJECT_NAME}'
|
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-web-secure.service=${ASCIINEMA_COMPOSE_PROJECT_NAME}'
|
||||||
- 'traefik.http.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}.loadbalancer.server.port=8080'
|
- 'traefik.http.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}.loadbalancer.server.port=4000'
|
||||||
# Admin interface - HTTP to HTTPS redirect
|
# Admin interface - HTTP to HTTPS redirect
|
||||||
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web.middlewares=${ASCIINEMA_COMPOSE_PROJECT_NAME}-redirect-web-secure'
|
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web.middlewares=${ASCIINEMA_COMPOSE_PROJECT_NAME}-redirect-web-secure'
|
||||||
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web.rule=Host(`admin.${ASCIINEMA_TRAEFIK_HOST}`)'
|
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web.rule=Host(`admin.${ASCIINEMA_TRAEFIK_HOST}`)'
|
||||||
@@ -59,7 +48,7 @@ services:
|
|||||||
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web-secure.entrypoints=web-secure'
|
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web-secure.entrypoints=web-secure'
|
||||||
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web-secure.middlewares=${ASCIINEMA_COMPOSE_PROJECT_NAME}-auth,${ASCIINEMA_COMPOSE_PROJECT_NAME}-compress,security-headers@file'
|
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web-secure.middlewares=${ASCIINEMA_COMPOSE_PROJECT_NAME}-auth,${ASCIINEMA_COMPOSE_PROJECT_NAME}-compress,security-headers@file'
|
||||||
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web-secure.service=${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin'
|
- 'traefik.http.routers.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin-web-secure.service=${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin'
|
||||||
- 'traefik.http.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin.loadbalancer.server.port=8080'
|
- 'traefik.http.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin.loadbalancer.server.port=4002'
|
||||||
# Network
|
# Network
|
||||||
- 'traefik.docker.network=${NETWORK_NAME}'
|
- 'traefik.docker.network=${NETWORK_NAME}'
|
||||||
# Watchtower
|
# Watchtower
|
||||||
|
|||||||
@@ -15,3 +15,15 @@ config :asciinema, Asciinema.Emails.Mailer,
|
|||||||
verify: :verify_none,
|
verify: :verify_none,
|
||||||
versions: [:"tlsv1.2", :"tlsv1.3"]
|
versions: [:"tlsv1.2", :"tlsv1.3"]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Serve custom theme files as static assets
|
||||||
|
config :asciinema, AsciinemaWeb.Endpoint,
|
||||||
|
static_url: [path: "/theme"],
|
||||||
|
check_origin: false
|
||||||
|
|
||||||
|
# Try to inject custom head HTML (if supported by asciinema)
|
||||||
|
config :asciinema, AsciinemaWeb.Endpoint,
|
||||||
|
extra_head_html: """
|
||||||
|
<link rel="stylesheet" href="/theme/custom.css">
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/theme/favicon.svg">
|
||||||
|
"""
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
# Map to determine which backend to use based on host
|
|
||||||
map $http_host $backend_port {
|
|
||||||
default 4000;
|
|
||||||
~^admin\. 4002;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 8080;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
# Proxy to actual asciinema server (port depends on subdomain)
|
|
||||||
location / {
|
|
||||||
proxy_pass http://asciinema_backend:$backend_port;
|
|
||||||
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;
|
|
||||||
|
|
||||||
# Inject custom JavaScript into HTML responses
|
|
||||||
sub_filter '</head>' '<script src="/theme/inject.js"></script></head>';
|
|
||||||
sub_filter_once on;
|
|
||||||
sub_filter_types text/html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Serve theme files directly
|
|
||||||
location /theme/ {
|
|
||||||
alias /theme/;
|
|
||||||
expires 1d;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// Inject custom theme CSS and favicon
|
|
||||||
(function() {
|
|
||||||
// Inject custom CSS
|
|
||||||
var link = document.createElement('link');
|
|
||||||
link.rel = 'stylesheet';
|
|
||||||
link.href = '/theme/custom.css';
|
|
||||||
document.head.appendChild(link);
|
|
||||||
|
|
||||||
// Inject custom favicon
|
|
||||||
var favicon = document.createElement('link');
|
|
||||||
favicon.rel = 'icon';
|
|
||||||
favicon.type = 'image/svg+xml';
|
|
||||||
favicon.href = '/theme/favicon.svg';
|
|
||||||
|
|
||||||
// Remove existing favicons first
|
|
||||||
var existingFavicons = document.querySelectorAll('link[rel*="icon"]');
|
|
||||||
existingFavicons.forEach(function(el) {
|
|
||||||
el.remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
document.head.appendChild(favicon);
|
|
||||||
})();
|
|
||||||
Reference in New Issue
Block a user