Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 24 additions & 12 deletions .env.example → .devcontainer/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,39 @@ OP_CONNECT_TOKEN=
# ============================================================================
# CUSTOM DOMAIN CONFIGURATION
# ============================================================================
# Two ways to allow custom domains:
# Two ways to allow custom domains beyond the built-in ones (GitHub, npm, Anthropic):
#
# 1. CUSTOM_ALLOWED_DOMAINS (below) - User/machine specific domains from .env
# - Stored in your local .env file (not committed to repo)
# 1. CUSTOM_ALLOWED_DOMAINS (below) - Personal/temporary domains from .env
# - Stored in your .devcontainer/.env file (not committed to repo)
# - For personal/local services (e.g., local test servers, personal APIs)
# - Processed at container startup
# - Comma-separated list of domains (without https://)
# - Supports: domain names, IP addresses, and CIDR ranges
#
# 2. allowed-domains.txt file - Project-wide domains
# - Create file in project root (committed to repo)
# - Create file in .devcontainer/ folder (committed to repo)
# - For team-shared domains (e.g., company APIs, private registries)
# - One domain/IP per line, supports comments with #
#
# Format: comma-separated list of domains (without https://)
# Example: CUSTOM_ALLOWED_DOMAINS=api.mycompany.com,registry.mycompany.io,192.168.1.100
# Supports: domain names, IP addresses, and CIDR ranges
# Example: CUSTOM_ALLOWED_DOMAINS=api.mycompany.com,staging.myapp.io,192.168.1.100
CUSTOM_ALLOWED_DOMAINS=

# ============================================================================
# SOCKS5 PROXY CONFIGURATION
# ============================================================================
# The container can use a SOCKS5 proxy running on your host machine
# Default port is 1080, accessible via host.docker.internal:1080
# To use with curl: curl --socks5 host.docker.internal:1080 https://example.com
# To use with git: git config --global http.proxy socks5://host.docker.internal:1080
# Configure access to a SOCKS5 proxy for routing traffic through a VPN or proxy server
# This is useful for accessing resources behind a corporate firewall or VPN

# Enable/disable SOCKS5 proxy access (true/false)
SOCKS5_ENABLED=true

# SOCKS5 proxy host (can be hostname or IP address)
# Default: host.docker.internal (your host machine)
# Examples: proxy.company.com, 192.168.1.100, host.docker.internal
SOCKS5_HOST=host.docker.internal

# SOCKS5 proxy port
SOCKS5_PORT=1080

# To use the proxy in the container:
# curl --socks5 ${SOCKS5_HOST}:${SOCKS5_PORT} https://example.com
# git config --global http.proxy socks5://${SOCKS5_HOST}:${SOCKS5_PORT}
9 changes: 9 additions & 0 deletions .devcontainer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Environment file with personal settings
.env

# Project-specific allowed domains (optional)
allowed-domains.txt

# But keep the examples
!.env.example
!allowed-domains.txt.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Custom Allowed Domains and IP Ranges
# Copy this file to 'allowed-domains.txt' in your project root to add custom allowed domains/IPs
#
#
# Format:
# - One entry per line
# - Domain names will be resolved to IPs (e.g., example.com)
Expand Down Expand Up @@ -28,7 +28,7 @@
# bedrock-runtime.eu-west-3.amazonaws.com
# bedrock-runtime.eu-central-1.amazonaws.com

# Asia Pacific Regions
# Asia Pacific Regions
# bedrock.ap-southeast-1.amazonaws.com
# bedrock.ap-southeast-2.amazonaws.com
# bedrock.ap-northeast-1.amazonaws.com
Expand Down
54 changes: 4 additions & 50 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
{
"name": "Liquescent Development Environment",
// Use pre-built image from GitHub Container Registry
// To build locally: cd docker-image && ./build.sh
"image": "ghcr.io/liquescent-development/devcontainer:latest",
"runArgs": [
"--cap-add=NET_ADMIN",
"--cap-add=NET_RAW",
"--add-host=host.docker.internal:host-gateway"
],
// Uses Docker Compose to load .env file automatically
"dockerComposeFile": "docker-compose.yml",
"service": "devcontainer",
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"extensions": [
Expand All @@ -17,7 +13,6 @@
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
Expand Down Expand Up @@ -55,52 +50,11 @@
},
"ghcr.io/itsmechlark/features/1password:1": {
"version": "latest"
},
"ghcr.io/devcontainers-community/features/direnv:1": {
"version": "latest"
}
},
"remoteUser": "node",
"userEnvProbe": "loginInteractiveShell",
"updateRemoteUserUID": true,
"secrets": {
"OP_SERVICE_ACCOUNT_TOKEN": {
"description": "1Password Service Account token for secure environment variable management",
"documentationUrl": "https://developer.1password.com/docs/service-accounts/"
},
"OP_CONNECT_TOKEN": {
"description": "1Password Connect Server token (alternative to service account)",
"documentationUrl": "https://developer.1password.com/docs/connect/"
}
},
"mounts": [
"source=devcontainer-history-${devcontainerId},target=/commandhistory,type=volume",
"source=${localEnv:HOME}/.claude/agents,target=/home/node/.claude/agents,type=bind,readonly",
"source=${localEnv:HOME}/.claude/CLAUDE.md,target=/home/node/.claude/CLAUDE.md,type=bind,readonly",
"source=${localEnv:HOME}/.claude/settings.json,target=/home/node/.claude/settings.json,type=bind,readonly",
"source=${localEnv:HOME}/Library/Fonts,target=/usr/share/fonts/truetype/custom,type=bind,readonly",
"source=${localEnv:HOME}/.gitconfig,target=/home/node/.gitconfig.host,type=bind,readonly",
"source=${localEnv:HOME}/.ssh,target=/home/node/.ssh-host,type=bind,readonly",
"source=${localEnv:SSH_AUTH_SOCK},target=/ssh-agent,type=bind"
],
"containerEnv": {
"NODE_OPTIONS": "--max-old-space-size=4096",
"CLAUDE_CONFIG_DIR": "/home/node/.claude",
"SSH_AUTH_SOCK": "/ssh-agent"
},
"remoteEnv": {
"OP_SERVICE_ACCOUNT_TOKEN": "${localEnv:OP_SERVICE_ACCOUNT_TOKEN}",
"OP_CREATE_SERVICE_ACCOUNT": "${localEnv:OP_CREATE_SERVICE_ACCOUNT}",
"OP_SA_EXPIRES_IN": "${localEnv:OP_SA_EXPIRES_IN}",
"OP_SA_VAULTS": "${localEnv:OP_SA_VAULTS}",
"OP_SA_NAME": "${localEnv:OP_SA_NAME}",
"OP_CONNECT_HOST": "${localEnv:OP_CONNECT_HOST}",
"OP_CONNECT_TOKEN": "${localEnv:OP_CONNECT_TOKEN}",
"CUSTOM_ALLOWED_DOMAINS": "${localEnv:CUSTOM_ALLOWED_DOMAINS}",
"MOUNT_HOST_GIT_CONFIG": "${localEnv:MOUNT_HOST_GIT_CONFIG}"
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace",
"hostRequirements": {
"cpus": 2,
"memory": "4gb",
Expand Down
77 changes: 77 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
services:
devcontainer:
image: ghcr.io/liquescent-development/devcontainer:latest

# Environment variables from .env file are automatically loaded
environment:
# Timezone
- TZ=${TZ:-UTC}

# 1Password Configuration
- OP_SERVICE_ACCOUNT_TOKEN=${OP_SERVICE_ACCOUNT_TOKEN:-}
- OP_CREATE_SERVICE_ACCOUNT=${OP_CREATE_SERVICE_ACCOUNT:-false}
- OP_SA_EXPIRES_IN=${OP_SA_EXPIRES_IN:-30d}
- OP_SA_VAULTS=${OP_SA_VAULTS:-}
- OP_SA_NAME=${OP_SA_NAME:-}
- OP_CONNECT_HOST=${OP_CONNECT_HOST:-}
- OP_CONNECT_TOKEN=${OP_CONNECT_TOKEN:-}

# Custom allowed domains for firewall
- CUSTOM_ALLOWED_DOMAINS=${CUSTOM_ALLOWED_DOMAINS:-}

# SOCKS5 proxy configuration
- SOCKS5_ENABLED=${SOCKS5_ENABLED:-true}
- SOCKS5_HOST=${SOCKS5_HOST:-host.docker.internal}
- SOCKS5_PORT=${SOCKS5_PORT:-1080}

# Git configuration mounting
- MOUNT_HOST_GIT_CONFIG=${MOUNT_HOST_GIT_CONFIG:-false}

# Container environment
- NODE_OPTIONS=--max-old-space-size=4096
- CLAUDE_CONFIG_DIR=/home/node/.claude
- SSH_AUTH_SOCK=/ssh-agent
- DEVCONTAINER=true

volumes:
# Workspace
- ..:/workspace:cached

# Claude configuration
- ${HOME}/.claude/agents:/home/node/.claude/agents:ro
- ${HOME}/.claude/CLAUDE.md:/home/node/.claude/CLAUDE.md:ro
- ${HOME}/.claude/settings.json:/home/node/.claude/settings.json:ro

# Git configuration and SSH
- ${HOME}/.gitconfig:/home/node/.gitconfig.host:ro
- ${HOME}/.ssh:/home/node/.ssh-host:ro

# SSH agent forwarding
- ${SSH_AUTH_SOCK:-/dev/null}:/ssh-agent

# Command history persistence
- devcontainer-history:/commandhistory

# Fonts (macOS specific path, will be ignored on other systems)
- ${HOME}/Library/Fonts:/usr/share/fonts/truetype/custom:ro

# Network capabilities for firewall
cap_add:
- NET_ADMIN
- NET_RAW

# Add host.docker.internal for accessing host services
extra_hosts:
- "host.docker.internal:host-gateway"

# Keep container running
command: sleep infinity

# Set working directory
working_dir: /workspace

# Run as node user
user: node

volumes:
devcontainer-history:
37 changes: 27 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ A secure, polyglot development container with network isolation, comprehensive l

2. **Configure your environment**:
```bash
cp .env.example .env
# Edit .env with your settings
cp .devcontainer/.env.example .devcontainer/.env
# Edit .devcontainer/.env with your settings
```

3. **Open in VS Code**:
Expand All @@ -58,7 +58,9 @@ The container will automatically pull from `ghcr.io/liquescent-development/devco

### Environment Variables

Key configuration options in `.env`:
The devcontainer uses Docker Compose to automatically load environment variables from `.devcontainer/.env`.

Key configuration options in `.devcontainer/.env`:

```bash
# Timezone
Expand Down Expand Up @@ -91,13 +93,14 @@ By default, only these domains are accessible:

**Method 1: Environment Variable** (personal/temporary)
```bash
# In .env
# In .devcontainer/.env
CUSTOM_ALLOWED_DOMAINS=api.example.com,db.internal.net
```

**Method 2: Project Configuration** (team/permanent)
Create an `allowed-domains.txt` file in `.devcontainer/`:
```bash
# In allowed-domains.txt (project root)
# In .devcontainer/allowed-domains.txt
api.example.com
staging.example.com
192.168.1.0/24
Expand Down Expand Up @@ -156,20 +159,34 @@ export API_KEY=$(op read "op://vault/item/field")

### Using SOCKS5 Proxy

Access external resources through host proxy:
The container supports configurable SOCKS5 proxy access for routing traffic through VPNs or corporate proxies.

Configuration in `.devcontainer/.env`:
```bash
SOCKS5_ENABLED=true # Enable/disable proxy access
SOCKS5_HOST=host.docker.internal # Proxy host (hostname or IP)
SOCKS5_PORT=1080 # Proxy port
```

Using the proxy in the container:
```bash
# Configure git
git config --global http.proxy socks5://host.docker.internal:1080
git config --global http.proxy socks5://${SOCKS5_HOST}:${SOCKS5_PORT}

# Use with curl
curl --socks5 host.docker.internal:1080 https://example.com
curl --socks5 ${SOCKS5_HOST}:${SOCKS5_PORT} https://example.com

# Use with Python
export HTTP_PROXY=socks5://host.docker.internal:1080
export HTTPS_PROXY=socks5://host.docker.internal:1080
export HTTP_PROXY=socks5://${SOCKS5_HOST}:${SOCKS5_PORT}
export HTTPS_PROXY=socks5://${SOCKS5_HOST}:${SOCKS5_PORT}
```

Common proxy scenarios:
- **Local SSH tunnel**: `ssh -D 1080 user@jumphost` then use default settings
- **Corporate proxy**: Set `SOCKS5_HOST` to your proxy server
- **VPN client**: Many VPN clients provide SOCKS5 on localhost:1080
- **Disable proxy**: Set `SOCKS5_ENABLED=false` if not needed

### Debugging Network Issues

```bash
Expand Down
2 changes: 1 addition & 1 deletion docker-image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
pkg-config \
libssl-dev \
# Note: direnv now installed via ghcr.io/devcontainers-community/features/direnv:1
direnv \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

# Note: 1Password CLI is now installed via Dev Container Feature:
Expand Down
Loading