Skip to content

feat: docker image + compose#2

Merged
ValwareIRC merged 3 commits into
unreal60_devfrom
feat/docker
May 2, 2026
Merged

feat: docker image + compose#2
ValwareIRC merged 3 commits into
unreal60_devfrom
feat/docker

Conversation

@ValwareIRC
Copy link
Copy Markdown

@ValwareIRC ValwareIRC commented May 2, 2026

Brings up a Docker deployment that builds straight from this fork's
source -- every native module (account-registration, persistence,
metadata, filehost, authtoken, smtp, obbyscript, ...) is compiled into
the image and ready to load.

Adapted from obbyworld/UnrealIRCd-Modules#10, refactored to drop the
upstream tarball download and the third-party module copy steps since
the equivalents already live in this tree.

Files

  • `docker/Dockerfile` -- alpine 3.19, pre-seeded `config.settings`
    drives `./Config -quick && make && make install`
    non-interactively. Builds as the `obbyircd` user; installs to
    `/home/obbyircd/obby/`.
  • `docker/docker-entrypoint.sh` -- first-run conf generation,
    self-signed TLS cert, random cloak keys, optional filehost / RPC
    blocks driven by env, custom-module compilation against the
    in-image source tree, `obbyircd -c` validation before exec.
  • `docker/obbyircd.conf.template` -- minimal but complete. TLS
    listen, WebSocket listen, account-registration block, default
    `admin/admin123` oper (change before exposing).
  • `compose.yaml` + `.env.example` -- one service, named volumes
    for conf/data/logs/tls/custom-modules with optional `*_BIND`
    overrides for bind mounts. Healthcheck on the TLS port.
  • `docker/README.md` -- usage, volume layout, env var reference,
    custom module workflow.
  • `.dockerignore` -- keeps build artifacts, the ObsidianIRC client
    checkout, and packaged `.deb`/`.rpm`/`.AppImage` outputs out of
    the build context.

Test plan

  • `docker build -f docker/Dockerfile -t obbyircd .`
  • `cp .env.example .env && docker compose up -d`
  • Connect: `ircs://localhost:6697`
  • `docker compose logs -f obbyircd`
  • Drop a `.c` file into the `obbyircd_custom_modules` volume,
    restart, confirm it compiled to `modules/third/`.

Summary by CodeRabbit

  • New Features

    • Docker containerization with Compose for easy deployment, persistent volumes, and a healthcheck.
    • Environment-variable configuration for server identity, ports, optional features (WebSocket, file hosting, JSON-RPC), and oper credentials.
    • First-run initialization, automatic TLS cert generation, oper-password persistence, and on-start custom module compilation.
  • Documentation

    • Full Docker deployment guide and an example .env template documenting configuration and runtime options.

Builds the IRCd straight from this repository so every native module
shipped with the fork (account-registration, persistence, metadata,
filehost, authtoken, smtp, obbyscript, ...) is compiled into the
image.

* docker/Dockerfile -- alpine 3.19, pre-seeded config.settings drives
  ./Config -quick && make && make install non-interactively.  Builds
  as the obbyircd user; installs to /home/obbyircd/obby/.
* docker/docker-entrypoint.sh -- on first run populates the conf
  volume from /etc/obbyircd/conf-defaults/, renders obbyircd.conf
  from the template via envsubst, issues a 1-day self-signed cert,
  generates random cloak keys.  Compiles any .c file dropped into the
  custom-modules volume against the in-image source tree.  Validates
  with `obbyircd -c` before exec.
* docker/obbyircd.conf.template -- minimal but complete: TLS listen,
  WebSocket listen, cloak keys, account-registration block, oper
  admin/admin123 default (change before use), and the optional
  filehost / RPC blocks injected by the entrypoint.
* compose.yaml -- one service, named volumes for conf/data/logs/tls/
  custom-modules with optional CONF_BIND/etc overrides.  Loads .env
  if present.  Healthcheck on the TLS port.
* .env.example -- documents every supported variable.
* docker/README.md -- usage, volume layout, env var reference, custom
  module workflow, cert replacement.
* .dockerignore -- keeps build artifacts, ObsidianIRC client checkout,
  packaged .deb/.rpm/.AppImage and CI noise out of the build context.

Adapted from obbyworld/UnrealIRCd-Modules#10; refactored to drop the
upstream tarball download and the third-party module copy steps since
the equivalents are already native modules in this tree.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 2, 2026

Warning

Rate limit exceeded

@ValwareIRC has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 54 minutes and 40 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6f85626c-49a0-4f96-9f52-a8a497281037

📥 Commits

Reviewing files that changed from the base of the PR and between e208430 and 61c43a7.

📒 Files selected for processing (3)
  • docker/Dockerfile
  • docker/README.md
  • docker/docker-entrypoint.sh
📝 Walkthrough

Walkthrough

Adds Docker-based packaging and orchestration for ObbyIRCd: build-stage Dockerfile, container entrypoint that initializes configuration/TLS and compiles optional modules, a conf template rendered from environment, Docker Compose and .env example for service/volumes/ports, and accompanying docs and ignore rules.

Changes

Docker Containerization Support

Layer / File(s) Summary
Context / Ignore rules
.dockerignore
Exclude build artifacts, generated config/build files, editor/CI noise, bundled release packages, docs artifacts, and local Docker outputs from build context.
Build image
docker/Dockerfile
Multi-stage build on alpine:3.19 that installs build/runtime deps, creates non-root user, copies source, pre-seeds config.settings, runs ./Config -quick + make/make install, snapshots installed default configs, creates runtime dirs, adds entrypoint and template, declares volumes, and sets ENTRYPOINT/CMD.
Entrypoint / Init logic
docker/docker-entrypoint.sh
Idempotent startup script that sets env defaults, generates cloak keys and self-signed TLS certs if missing, persists/generates OPER_PASSWORD, renders docker/obbyircd.conf.template via envsubst on first run, compiles custom-modules/*.c into modules/third/, validates config (./bin/obbyircd -c) and starts the server as the obbyircd user.
Configuration template
docker/obbyircd.conf.template
Env-substituted server config with placeholders for identity, admin, TLS listener, operator block, optional WebSocket/filehost/RPC fragments, cloak keys, and account-registration policy.
Orchestration / Environment
compose.yaml, .env.example
Docker Compose service obbyircd built from docker/Dockerfile, restarts unless-stopped, loads .env, maps host ports to ${SSL_HOST_PORT}:${SSL_PORT} and ${WS_HOST_PORT}:${WS_PORT}, mounts five named volumes (obbyircd_conf, obbyircd_data, obbyircd_logs, obbyircd_tls, obbyircd_custom_modules), includes an nc healthcheck, and ships an .env.example documenting identity, ports, oper credentials, optional features, cloak keys, and bind-mount override variables.
Documentation
docker/README.md
Run/build instructions, first-run behavior (config rendering, TLS and cloak key generation), persistence and reset guidance, connection endpoints, default oper credentials, env var reference, custom-module workflow, TLS replacement steps, and manual build command.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DockerCompose
    participant Container
    participant VolumeFS
    participant ObbyIRCdBin

    User->>DockerCompose: docker compose up -d
    DockerCompose->>Container: create & start container (mount volumes, env)
    Container->>VolumeFS: check conf/.docker_initialized, conf and data dirs
    alt first run
        Container->>VolumeFS: copy /etc/obbyircd/conf-defaults -> conf
        Container->>Container: render template via envsubst
        Container->>Container: generate cloak keys & self-signed certs
    end
    Container->>VolumeFS: persist OPER_PASSWORD if generated
    Container->>Container: compile custom-modules/*.c -> modules/third/*.so
    Container->>ObbyIRCdBin: run ./bin/obbyircd -c (validate)
    alt validation success
        Container->>ObbyIRCdBin: exec su-exec obbyircd ./bin/obbyircd -F
    else validation failure
        Container-->>DockerCompose: exit 1 (fail start)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

🐇 in a snug docker den I hop and spin,

configs rendered, keys born on a whim,
modules compiled with a merry clack,
ports exposed so friends may pack,
my IRC burrow hums — logs crackle, servers grin.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: docker image + compose' accurately summarizes the main change—adding Docker image and compose configuration for deploying ObbyIRCd.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/docker

Tip

💬 Introducing Slack Agent: Turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 54 minutes and 40 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docker/docker-entrypoint.sh`:
- Around line 90-99: The TLS bootstrap (the if that checks
"$TLS_DIR/server.cert.pem" and "$TLS_DIR/server.key.pem") must be moved out of
the initial "conf/.docker_initialized" first-run gating so cert creation runs on
every start when the TLS volume lacks keys; update docker-entrypoint.sh to run
the existing openssl-generation block unconditionally (or in its own conditional
only checking for the cert/key files) rather than inside the conf-init block,
keep the same file checks, permissions (chmod 600/644) and subject
("/CN=$SERVER_NAME"), and ensure the logic is idempotent so a replaced/empty TLS
volume self-heals by generating new cert/key.
- Around line 101-104: Delay creating and chown'ing the marker file until after
the generated config is validated: generate the config into a temp file, run the
validator ./bin/obbyircd -c against that temp file, and only if that command
exits successfully promote the temp file into place and then run chown -R
obbyircd:obbyircd "$CONF_DIR" "$TLS_DIR" "$DATA_DIR" "$LOGS_DIR", touch
"$FIRST_RUN_MARKER" and chown "$FIRST_RUN_MARKER" (apply the same change to the
other marker creation block referenced around the later 136-140 region); ensure
failures abort without creating the marker so a fixed environment will re-render
on next start.

In `@docker/obbyircd.conf.template`:
- Around line 46-53: The shipped oper block defines a default admin credential
(oper admin { mask *; password "admin123"; ... }) which is insecure; replace the
hardcoded password by reading it from an environment variable or a first-run
generated secret (e.g., use ${OPER_PASSWORD} or generate/store a random secret
at container startup) and remove the literal "admin123" from the oper
definition, keep the oper name/class/rights (oper admin, class clients,
operclass netadmin, swhois, vhost) intact; additionally update .env.example and
docker/README.md to document the new OPER_PASSWORD variable and describe
first-run generation/where the secret is persisted.

In `@docker/README.md`:
- Around line 78-84: Replace the hard-coded host-side volume copy in the README
by showing a portable container-targeted copy or referencing the
CUSTOM_MODULES_BIND variable: instruct readers to run "docker compose cp
my-extra-module.c obbyircd:/home/obbyircd/obby/custom-modules/" (targeting the
obbyircd container) or alternatively call out using the CUSTOM_MODULES_BIND
configuration to mount custom modules, then tell them to restart or rehash
obbyircd and add `loadmodule "third/my-extra-module";` to obbyircd.conf; update
the example text around the cp/rehash steps and mention CUSTOM_MODULES_BIND as
the preferred portable approach.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b572106f-b120-4ef1-a863-e0f0270bad46

📥 Commits

Reviewing files that changed from the base of the PR and between 0e3c595 and b72c8c6.

📒 Files selected for processing (7)
  • .dockerignore
  • .env.example
  • compose.yaml
  • docker/Dockerfile
  • docker/README.md
  • docker/docker-entrypoint.sh
  • docker/obbyircd.conf.template

Comment thread docker/docker-entrypoint.sh Outdated
Comment thread docker/docker-entrypoint.sh Outdated
Comment thread docker/obbyircd.conf.template Outdated
Comment thread docker/README.md
* Move TLS cert bootstrap out of the conf-init block so a
  fresh-but-empty tls volume self-heals on every start (was previously
  gated by conf/.docker_initialized -- replacing only the tls volume
  would leave the server with no cert and configtest would fail).
* Defer writing .docker_initialized until after `obbyircd -c` succeeds.
  An invalid first render now leaves the marker absent so fixing the
  offending env var and restarting re-renders.
* Drop the shipped `admin123` oper password.  OPER_NAME / OPER_PASSWORD
  / OPER_MASK are env-driven; if OPER_PASSWORD is unset on first run, a
  random secret is generated, persisted to data/.oper_password, and
  printed once to the container log.
* Replace the host-path volume copy example in docker/README.md with
  `docker compose cp` (which works on rootful, rootless and podman),
  and document the CUSTOM_MODULES_BIND alternative for direct host
  edits.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docker/docker-entrypoint.sh (1)

187-191: ⚡ Quick win

Remove redundant conditional.

Both branches execute identical code (exec su-exec obbyircd "$@"), making the condition at lines 188-190 dead logic.

♻️ Proposed fix
 echo "Starting ObbyIRCd..."
-if [ "$#" -ge 2 ] && [ "$1" = "./bin/obbyircd" ] && [ "$2" = "-F" ]; then
-    exec su-exec obbyircd "$@"
-fi
 exec su-exec obbyircd "$@"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker/docker-entrypoint.sh` around lines 187 - 191, In docker-entrypoint.sh
remove the redundant if block that checks '[ "$#" -ge 2 ] && [ "$1" =
"./bin/obbyircd" ] && [ "$2" = "-F" ]' since both branches call the same exec
(exec su-exec obbyircd "$@"); replace the whole conditional with a single
unconditional exec su-exec obbyircd "$@" to simplify the script and eliminate
dead logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docker/docker-entrypoint.sh`:
- Around line 187-191: In docker-entrypoint.sh remove the redundant if block
that checks '[ "$#" -ge 2 ] && [ "$1" = "./bin/obbyircd" ] && [ "$2" = "-F" ]'
since both branches call the same exec (exec su-exec obbyircd "$@"); replace the
whole conditional with a single unconditional exec su-exec obbyircd "$@" to
simplify the script and eliminate dead logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 85e4d812-c593-4db8-a033-f5f98d6eb6b5

📥 Commits

Reviewing files that changed from the base of the PR and between b72c8c6 and e208430.

📒 Files selected for processing (4)
  • .env.example
  • docker/README.md
  • docker/docker-entrypoint.sh
  • docker/obbyircd.conf.template
✅ Files skipped from review due to trivial changes (2)
  • docker/README.md
  • docker/obbyircd.conf.template

`make install` doesn't copy doc/conf/scripts/, so the obbyscript
module logged a JS_SCRIPTS_DIR_NOT_FOUND warning on every start in
the docker image.

* Dockerfile: copy doc/conf/scripts/*.js into the conf-defaults
  snapshot so first-run pre-populates conf/scripts/example.js.
* Entrypoint: mkdir -p $CONF_DIR/scripts on every start, chown to
  obbyircd, so the directory self-heals if an operator wipes it.
* README: document where JS scripts go and how to add/replace them
  via `docker compose cp`.

No new volume or env var; scripts continue to live alongside the
config inside the obbyircd_conf volume.
@ValwareIRC ValwareIRC merged commit b36b24e into unreal60_dev May 2, 2026
1 check passed
@coderabbitai coderabbitai Bot mentioned this pull request May 3, 2026
@ValwareIRC ValwareIRC deleted the feat/docker branch May 3, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant