diff --git a/asciinema/compose.yaml b/asciinema/compose.yaml
index 7e68922..e436441 100644
--- a/asciinema/compose.yaml
+++ b/asciinema/compose.yaml
@@ -1,14 +1,13 @@
services:
- asciinema:
+ asciinema_backend:
image: ${ASCIINEMA_IMAGE:-ghcr.io/asciinema/asciinema-server:latest}
- container_name: ${ASCIINEMA_COMPOSE_PROJECT_NAME}_app
+ container_name: ${ASCIINEMA_COMPOSE_PROJECT_NAME}_backend
restart: unless-stopped
networks:
- compose_network
volumes:
- asciinema_data:/var/opt/asciinema
- ./custom.exs:/opt/app/etc/custom.exs:ro
- - ./theme:/opt/app/etc/theme:ro
environment:
SECRET_KEY_BASE: ${ASCIINEMA_SECRET_KEY}
URL_HOST: ${ASCIINEMA_TRAEFIK_HOST}
@@ -20,6 +19,18 @@ services:
SMTP_FROM_ADDRESS: ${EMAIL_FROM}
SIGN_UP_DISABLED: ${ASCIINEMA_SIGN_UP_DISABLED:-false}
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:
- 'traefik.enable=${ASCIINEMA_TRAEFIK_ENABLED}'
# Main web interface - HTTP to HTTPS redirect
@@ -35,7 +46,7 @@ services:
- '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.service=${ASCIINEMA_COMPOSE_PROJECT_NAME}'
- - 'traefik.http.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}.loadbalancer.server.port=4000'
+ - 'traefik.http.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}.loadbalancer.server.port=8080'
# 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.rule=Host(`admin.${ASCIINEMA_TRAEFIK_HOST}`)'
@@ -48,7 +59,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.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.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin.loadbalancer.server.port=4002'
+ - 'traefik.http.services.${ASCIINEMA_COMPOSE_PROJECT_NAME}-admin.loadbalancer.server.port=8080'
# Network
- 'traefik.docker.network=${NETWORK_NAME}'
# Watchtower
diff --git a/asciinema/custom.exs b/asciinema/custom.exs
index a1cc669..dd1b726 100644
--- a/asciinema/custom.exs
+++ b/asciinema/custom.exs
@@ -15,58 +15,3 @@ config :asciinema, Asciinema.Emails.Mailer,
verify: :verify_none,
versions: [:"tlsv1.2", :"tlsv1.3"]
]
-
-# Custom theme configuration - inject custom CSS and favicon
-defmodule AsciinemaWeb.CustomThemePlug do
- @moduledoc """
- Plug to inject custom CSS and favicon into HTML responses
- """
- import Plug.Conn
-
- def init(opts), do: opts
-
- def call(conn, _opts) do
- register_before_send(conn, fn conn ->
- if html_response?(conn) do
- inject_custom_theme(conn)
- else
- conn
- end
- end)
- end
-
- defp html_response?(conn) do
- case get_resp_header(conn, "content-type") do
- [content_type | _] -> String.contains?(content_type, "text/html")
- [] -> false
- end
- end
-
- defp inject_custom_theme(conn) do
- custom_head = """
-
-
- """
-
- case conn.resp_body do
- body when is_binary(body) ->
- new_body = String.replace(body, "", "#{custom_head}")
- %{conn | resp_body: new_body}
- _ ->
- conn
- end
- end
-end
-
-# Configure Phoenix endpoint to serve custom theme files
-config :asciinema, AsciinemaWeb.Endpoint,
- # Serve theme files from /opt/app/etc/theme
- static_dirs: %{
- at: "/theme",
- from: "/opt/app/etc/theme",
- gzip: false
- }
-
-# Inject the custom theme Plug into the endpoint
-config :asciinema, AsciinemaWeb.Endpoint,
- plug: AsciinemaWeb.CustomThemePlug
diff --git a/asciinema/nginx/nginx.conf b/asciinema/nginx/nginx.conf
new file mode 100644
index 0000000..bbfadb2
--- /dev/null
+++ b/asciinema/nginx/nginx.conf
@@ -0,0 +1,40 @@
+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 '' '';
+ 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";
+ }
+ }
+}
diff --git a/asciinema/theme/favicon.svg b/asciinema/theme/favicon.svg
index 2a96a8b..284333a 100644
--- a/asciinema/theme/favicon.svg
+++ b/asciinema/theme/favicon.svg
@@ -1,24 +1,3 @@
-
+
\ No newline at end of file
diff --git a/asciinema/theme/inject.js b/asciinema/theme/inject.js
new file mode 100644
index 0000000..aa34e69
--- /dev/null
+++ b/asciinema/theme/inject.js
@@ -0,0 +1,22 @@
+// 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);
+})();