Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5e545bc
Implement instance fallback generator with Docker setup, error handli…
The0mikkel Nov 13, 2025
aaa14f1
Add local development guide
The0mikkel Nov 13, 2025
b8a985e
Update wording of auto-page reload and request of support
The0mikkel Nov 14, 2025
8ee8d28
Remove redundant code
The0mikkel Nov 14, 2025
5f15a4f
Update html formatting to fit standard
The0mikkel Nov 14, 2025
9c5ebe5
Update formatting to fit linting standards
The0mikkel Nov 14, 2025
40cd5c9
Add language and charset attributes to HTML files for better accessib…
The0mikkel Nov 14, 2025
12e2731
Refactor error handling in challenge readiness check and improve logging
The0mikkel Nov 14, 2025
f44ab57
Fix error handling in challenge readiness check to ensure all promise…
The0mikkel Nov 14, 2025
1401e6b
Add noscript fallback
The0mikkel Nov 14, 2025
95ac652
Add instant challenge ready check
The0mikkel Nov 14, 2025
6f71a71
Fix formatting issues
The0mikkel Nov 14, 2025
3a6e065
Update error message in 404 page for clarity
The0mikkel Nov 14, 2025
c3d710f
Add viewport meta tag to error and standard HTML layouts for better r…
The0mikkel Nov 14, 2025
60aac4e
Enhance replace_indented_placeholder function with detailed docstring…
The0mikkel Nov 14, 2025
ce5fb40
Fix capitalization of "JavaScript" in noscript messages for consistency
The0mikkel Nov 14, 2025
ba29e5d
feat: instance fallback service (#1)
The0mikkel Nov 14, 2025
30cefdd
feat: add release system
The0mikkel Nov 14, 2025
a618824
Add CODEOWNERS file for release configuration
The0mikkel Nov 14, 2025
727c715
fix(ci): update release system to use Release environment
The0mikkel Nov 15, 2025
0f2f0f4
Correct CI release workflow to use environment
The0mikkel Nov 15, 2025
fa055a1
Add github token to secrets
The0mikkel Nov 15, 2025
1b971e5
chore(release): 1.0.0-r.2 [skip ci]
semantic-release-bot Nov 15, 2025
46703fa
fix(workflows): update CLA Assistant and Release workflows to use int…
The0mikkel Nov 15, 2025
61a9d4d
Correct repository name in release workflow
The0mikkel Nov 15, 2025
d0004ef
Update CI version
The0mikkel Nov 15, 2025
b736e97
Add delay before reloading on error during challenge readiness check
The0mikkel Nov 16, 2025
37968be
Clean up formatting in error 404 message
The0mikkel Nov 16, 2025
f1d514a
Update CLA Assistant to use version v1.1.2
The0mikkel Nov 16, 2025
bc5e50b
Add update-develop job to release workflow for automatic branch updates
The0mikkel Nov 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 4 additions & 26 deletions .github/workflows/cla-assistant.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,7 @@ permissions:
jobs:
CLAAssistant:
name: "CLA Assistant"
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
uses: contributor-assistant/github-action@v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_ASSISTANT_PAT }}
with:
path-to-signatures: "signatures/instancing-fallback/v1/cla.json"
path-to-document: "https://github.com/ctfpilot/cla/blob/1a3a56410df569e0672aafd508044da85f194e8b/CLA.md"

# branch should not be protected
branch: "main"
allowlist: ""
lock-pullrequest-aftermerge: false
use-dco-flag: false

# Remote CLA repo
remote-organization-name: "ctfpilot"
remote-repository-name: "cla"
create-file-commit-message: "Creating file for storing CLA Signatures"
signed-commit-message: "$contributorName has signed the CLA in $owner/$repo"
custom-notsigned-prcomment: 'Thank you for your contribution! Before we can proceed, please sign the Contributor License Agreement (CLA) by replying to this comment with "I have read the CLA Document and I hereby sign the CLA". You can find the CLA document [here](https://github.com/ctfpilot/cla/blob/1a3a56410df569e0672aafd508044da85f194e8b/CLA.md).'
custom-pr-sign-comment: "I have read the CLA Document and I hereby sign the CLA"
custom-allsigned-prcomment: "All Contributors have signed the CLA. Thank you for your cooperation!"
uses: ctfpilot/ci/.github/workflows/cla-assistant.yml@v1.1.2
secrets: inherit
with:
repository: instance-fallback
37 changes: 35 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,38 @@ jobs:
packages: write
id-token: write
name: Release
if: github.repository == 'ctfpilot/instancing-fallback'
uses: the0mikkel/ci/.github/workflows/semver-release-standalone.yml@v1.4.0
uses: ctfpilot/ci/.github/workflows/release.yml@v1.1.1
secrets:
RELEASE_GH_TOKEN: ${{ secrets.RELEASE_GH_TOKEN }}
with:
repository: ctfpilot/instancing-fallback
ENVIRONMENT: Release

docker:
name: Docker build and push
needs:
- release
uses: ctfpilot/ci/.github/workflows/docker.yml@v1.1.1
if: needs.release.outputs.version != '' && needs.release.outputs.version != null
permissions:
contents: read
packages: write
id-token: write
with:
repository: ctfpilot/instancing-fallback
semver: ${{ needs.release.outputs.version }}
arguments: |
VERSION=${{ needs.release.outputs.version }}

update-develop:
if: github.ref == 'refs/heads/main'
name: "Update Develop Branch"
needs:
- release
uses: ctfpilot/ci/.github/workflows/develop-update.yml@v1.2.0
permissions:
contents: read
pull-requests: write
issues: write
with:
repository: ctfpilot/instancing-fallback
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public/
6 changes: 4 additions & 2 deletions .releaserc.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@
[
"@semantic-release/exec",
{
"prepareCmd": "echo ${nextRelease.version} > version.txt",
"prepareCmd": "echo ${nextRelease.version} > version.txt && cp template/k8s.yml k8s/k8s.yml && sed -i 's/{ .Version }/${nextRelease.version}/g' k8s/k8s.yml",
"publishCmd": "echo 'Published version ${nextRelease.version}'"
}
],
[
"@semantic-release/git",
{
"assets": [],
"assets": [
"k8s/k8s.yml"
],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
]
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Require review from security/maintainers for workflows
.releaserc.json @ctfpilot/devops
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM python:3.14-slim AS builder

WORKDIR /app

COPY src/ /app/src

RUN python3 src/generator.py

FROM joseluisq/static-web-server

COPY --from=builder /app/public/ /public

ENV SERVER_CACHE_CONTROL_HEADERS=false
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ The service can also be run locally, using the provided Docker compose file:
docker compose up -d
```

### Development

In order to generate the pages, run the [`generator.py`](./src/generator.py) script in `src`:

```sh
python3 src/generator.py
```

*This is done automatically in the Docker container build process.*

## Contributing

We welcome contributions of all kinds, from **code** and **documentation** to **bug reports** and **feedback**!
Expand Down
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
services:
instancing-fallback:
build: .
ports:
- "8080:80"
restart: always
development:
image: joseluisq/static-web-server
ports:
- "8081:80"
volumes:
- ./public:/public
restart: always
63 changes: 63 additions & 0 deletions k8s/k8s.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: instance-fallback
labels:
app.kubernetes.io/part-of: ctfpilot
app.kubernetes.io/name: instance-fallback
app.kubernetes.io/version: 1.0.0-r.2
app.kubernetes.io/component: challenges
ctfpilot.com/component: instance-fallback

spec:
# HA setup
replicas: 3
selector:
matchLabels:
ctfpilot.com/component: instance-fallback

template:
metadata:
labels:
ctfpilot.com/component: instance-fallback
spec:
enableServiceLinks: false
automountServiceAccountToken: false
containers:
- name: instancing-fallback
image: ctfpilot/instance-fallback:1.0.0-r.2
imagePullPolicy: Always
ports:
- name: http
containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "10m"
limits:
memory: "256Mi"
cpu: "100m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: instance-fallback
labels:
app.kubernetes.io/part-of: ctfpilot
app.kubernetes.io/name: instance-fallback
app.kubernetes.io/version: 1.0.0-r.2
app.kubernetes.io/component: challenges
ctfpilot.com/component: instance-fallback
spec:
selector:
ctfpilot.com/component: instance-fallback
ports:
- name: http
port: 80
targetPort: http
7 changes: 7 additions & 0 deletions src/content/error_404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<h1>The challenge instance is offline</h1>
<p>
Please start your challenge or wait a few moments for the instance to become available, if you have already started
it. <br />
This may take a few minutes. You may see "No Available Server", "Bad Gateway" or "Service Unavailable", this is
normal and you will just need to wait a bit longer.
</p>
4 changes: 4 additions & 0 deletions src/content/error_502.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<h1>Bad gateway</h1>
<p>
The challenge did not answer correctly. Your challenge may still be starting up.
</p>
4 changes: 4 additions & 0 deletions src/content/error_503.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<h1>Your personal challenge instance is starting</h1>
<p>
The challenge is not yet ready. Please wait a few moments for the instance to become available.
</p>
6 changes: 6 additions & 0 deletions src/content/error_504.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<h1>Gateway timeout</h1>
<p>
The challenge was too slow to respond. <br />
This may either indicate that your challenge is still starting up, or that the action you took made the
server not respond in time.
</p>
7 changes: 7 additions & 0 deletions src/content/standard_index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<h1>The challenge instance is offline</h1>
<p>
Please start the challenge or wait a few moments for the instance to become available, if you have already
started it. <br />
This may take a few minutes. You may see "No Available Server", "Bad Gateway" or "Service Unavailable", this
is normal and you will just need to wait a bit longer.
</p>
72 changes: 72 additions & 0 deletions src/css/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
:root {
--header-font: "Hack", monospace, sans-serif;
--body-font: "Hack", monospace, sans-serif;

--light-theme-color: #eebc1d;
--dark-theme-color: #eebc1d;
--text-light: #232323;
--text-dark: #f9f9f9;
--bg-light: #f9f9f9;
--bg-dark: #232323;

--theme-color: var(--light-theme-color);
--bg-color: var(--bg-light);
--text-color: var(--text-light);
}

@media (prefers-color-scheme: dark) {
:root {
--theme-color: var(--dark-theme-color);
--bg-color: var(--bg-dark);
--text-color: var(--text-dark);
}
}

html,
body {
background-color: var(--bg-color);
color: var(--text-color) !important;
font-family: var(--body-font) !important;
margin: 0;
padding: 0;
}

main {
padding: 2rem;
}

h1,
h2,
h3,
h4,
h5 {
font-family: var(--header-font) !important;
}

a {
color: var(--theme-color);
filter: brightness(100%);
transition: filter 0.2s;
}

a:hover {
filter: brightness(95%);
transition: filter 0.2s;
}

.container {
display: flex;
justify-content: center;
text-align: center;
height: 100vh;
overflow-y: hidden;
align-items: center;
}

.challenge-loading {
display: none;
}

.wrong-domain {
display: none;
}
Loading
Loading