DevCon 4

DEFCON (Defense Readiness Condition) is the US military alert system. DEFCON 5 is peacetime. DEFCON 1 is nuclear war.

DevCon 4 is where we operate: heightened awareness, not full lockdown. Your development container is secured with a restrictive firewall, but you still have access to everything you need -- GitHub, Hex, Anthropic. Vigilant, but productive.

Devcontainer setup for Elixir projects. A Mix archive installer that generates a complete .devcontainer/ configuration with Claude Code, a restrictive firewall, and development tools.

What it generates

Three files are created in your project's .devcontainer/ directory:

File Purpose
devcontainer.json Container settings, volume mounts, VS Code extensions, and lifecycle commands
Dockerfile Elixir + Node.js image with Claude Code, zsh, git, and firewall tools
init-firewall.sh Restrictive outbound firewall allowing only essential domains

Dockerfile details

The generated Dockerfile builds an image with:

Firewall details

The init-firewall.sh script applies a default-deny outbound policy, allowing only these domains:

Domain Reason
api.github.com, GitHub IP ranges Git operations, GitHub CLI
registry.npmjs.org Claude Code installation/updates
api.anthropic.com Claude Code API access
sentry.io Claude Code error reporting
statsig.anthropic.com, statsig.com Claude Code telemetry
repo.hex.pm, builds.hex.pm, hex.pm Elixir package management

DNS (port 53), SSH (port 22), and localhost are always allowed.

Installation

mix archive.install hex devcon4

Usage

Run in any Elixir project:

mix devcon4.install

Options

All options have sensible defaults. Override them as needed:

Option Default Description
--elixir-version1.18.3 Elixir version for the base Docker image
--erlang-version27.3.3 Erlang/OTP version for the base Docker image
--ubuntu-versionnoble Ubuntu release codename
--ubuntu-date-tag20260217 Ubuntu image date tag from hexpm/elixir
--timezoneAmerica/Sao_Paulo Default timezone fallback (host $TZ takes priority)
--forcefalse Overwrite existing files without prompting

Examples

Install with defaults:

mix devcon4.install

Install with custom Elixir/Erlang versions:

mix devcon4.install \
  --elixir-version 1.17.0 \
  --erlang-version 26.2.1

Starting the container

Via terminal (devcontainer CLI)

# Build and start the container
devcontainer up --workspace-folder .

# Execute commands inside the container
devcontainer exec --workspace-folder . mix test
devcontainer exec --workspace-folder . claude

# Enter an interactive shell
docker exec -it <container_id> zsh

# Rebuild after changing devcontainer files
devcontainer up --workspace-folder . --rebuild-if-exists

Via VS Code

  1. Install the Dev Containers extension
  2. Open the project folder
  3. Press Ctrl+Shift+P and select Dev Containers: Reopen in Container
  4. The ElixirLS extension is automatically installed

Using Claude Code inside the container

Once inside the container, Claude Code is available globally:

claude                    # Start Claude Code
claude --dangerously-skip-permissions  # Unattended mode (use with caution)

The Claude Code configuration is persisted across container rebuilds via a Docker volume mounted at /home/developer/.claude.

Customization

After installation, the generated files are yours to modify. Common customizations:

Adding firewall domains

Edit .devcontainer/init-firewall.sh and add domains to the for domain in loop:

for domain in \
    "registry.npmjs.org" \
    "api.anthropic.com" \
    ...
    "your-domain.example.com"; do   # <-- add here

Adding system packages

Edit .devcontainer/Dockerfile and add packages to the apt-get install line:

RUN apt-get update && apt-get install -y --no-install-recommends \
  ...
  postgresql-client \   # <-- add here
  && apt-get clean && rm -rf /var/lib/apt/lists/*

Adding VS Code extensions

Edit .devcontainer/devcontainer.json:

"customizations": {
  "vscode": {
    "extensions": [
      "JakeBecker.elixir-ls",
      "your.extension-id"
    ]
  }
}

Changing container settings

Edit .devcontainer/devcontainer.json. Common changes:

Security considerations

The firewall restricts outbound network access to a whitelist of domains. This provides meaningful isolation but is not a complete sandbox:

Only use devcontainers with repositories you trust.

The --dangerously-skip-permissions flag for Claude Code is designed for use within this restricted environment. It allows Claude Code to operate without interactive permission prompts, which is useful for automated workflows. The firewall limits the blast radius of any unintended actions.

Finding available image tags

The base image tag follows the pattern hexpm/elixir:{elixir}-erlang-{erlang}-ubuntu-{ubuntu}-{date}. To find available tags:

# Search for tags matching your desired versions
curl -s "https://hub.docker.com/v2/repositories/hexpm/elixir/tags?page_size=100&name=1.18" \
  | jq -r '.results[].name' | grep noble | sort -V

License

Apache-2.0