forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
forked from NeKzor/board

Repository files navigation

mel.board.portal2.sr

Challenge Mode Leaderboard for Portal 2 Mods.

Local Development

Requirements:

Steps:

  • Project setup with ./setup dev
  • Copy cp docker/compose/board.portal2.local.yml docker-compose.yml
  • Start the containers with docker compose up
  • Add the host entry 127.0.0.1 board.portal2.local to /etc/hosts

The server should now be available at: https://board.portal2.local

Caveats

  • Permissions have to be managed manually for mounted volumes, see moby#2259
  • MySQL 8 container leaks memory, see containerd#6707

Overview of .env

This is used by Dockerfile and docker-compose.yml.

VariableDescription
PROJECT_NAMEThis name is used as a prefix for the containers.
SERVER_NAMEThe domain name which should be set before building the image. Docker will use it to mount the correct apache config file which links to the SSL certificates.
HTTP_PORTThe unsafe HTTP port of the local host. Change it if a different port is needed e.g. reverse proxy
HTTPS_PORTThe safe HTTPS port of the local host. Change it if a different port is needed e.g. reverse proxy
DATABASE_PORTThe MySQL database port of the local host. NOTE: Make sure that the docker compose file does not expose the server to an unwanted address. By default it's mapped to 127.0.0.1.
MYSQL_ROOT_PASSWORDThe root's password of the MySQL database.
APT_PACKAGESOptional apt-packages to build the server image. The image should be kept as small as possible but sometimes it is useful to install some packages (e.g. vim, htop etc.) in order to debug problems more quickly.
UIDUser Identifier of host to map to www-data inside the container. Only relevant on Linux.
GIDGroup Identifier of host to map to www-data inside the container. Only relevant on Linux.

Overview of .config.json

This is used by the server.

KeyDescription
database_hostAddress of the database. Docker creates a link to the container under the database alias.
database_userUser login name for database.
database_passUser password for database access.
database_nameThe database name.
discord_webhook_wrDiscord webhook URL for sending world record updates to a Discord channel.
discord_webhook_mdpDiscord webhook URL for sending mdp data to a Discord channel.
steam_api_keyThe Steam Web API Key for fetching profile data.

Production

Mostly the same as in development but use ./setup prod instead.

  • Open .env file and set SERVER_NAME to the server domain
  • Copy cp docker/compose/mel.board.portal2.sr.yml docker-compose.yml
  • Finally use docker compose up -d

Reverse Proxy (recommended)

A host might use a reverse proxy like Nginx for managing other web applications. This makes managing sub-domains and SSL certificates much easier. Of course this part can also be inside a docker container but it is left out in this example.

Make sure that the docker composer file uses a local address that can only be reached within the host's network, or the container ports might get exposed to the public. The example below assumes that nobody will call the container from the outside and the inside except Nginx. Otherwise enable apache mod remoteip and add RemoteIPHeader with RemoteIPTrustedProxy to the apache config. This will verify if the requests are coming from the reverse proxy only.

~/$ cat .env
PROJECT_NAME=board
SERVER_NAME=mel.board.portal2.sr
HTTP_PORT=8880
HTTPS_PORT=8443
DATABASE_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=board
MYSQL_PASSWORD=board
MYSQL_DATABASE=board
APT_PACKAGES=
UID=1001
GID=1001
View example Nginx config file
~/$ cat /etc/nginx/sites-available/mel.board.portal2.sr
server {
listen 80;
server_name mel.board.portal2.sr;return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name mel.board.portal2.sr;
ssl_certificate /etc/letsencrypt/live/mel.board.portal2.sr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mel.board.portal2.sr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
}
location /uploadDemo {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /submitChange {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
location /api-v2/auto-submit {
proxy_pass http://127.0.0.1:8443$request_uri;
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_buffering off;
client_max_body_size 16M;
}
}

Testing

Regression tests are written in TypeScript and require the Deno runtime. Make sure to fill out the AUTH_HASH and COOKIE constants.

just test

Credits

  • Originally developed and designed by ncla (2014-2015)
  • Further development by iVerb (2016-2020)

License

Software licensed under CC Attribution - Non-commercial license. https://creativecommons.org/licenses/by-nc/4.0/legalcode

About

Secure version of board.portal2.sr running on PHP 8.1 + Docker 💩

Resources

Stars

0 stars

Watchers

0 watching

Forks

Sponsor this project

Contributors

Languages