diff --git a/docker-compose.yml b/docker-compose.yml index 36054b4..4995b56 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,7 +83,7 @@ services: - "${MKDOCS_PORT:-4000}:8000" environment: - SITE_URL=${BASE_DOMAIN:-https://changeme.org} - command: serve --dev-addr=0.0.0.0:8000 --watch-theme --livereload --dirty + command: serve --dev-addr=0.0.0.0:8000 --watch-theme --livereload networks: - changemaker-lite restart: unless-stopped diff --git a/mkdocs/.cache/plugin/social/08c3137589ee1e07c6b82c5f3e9e47bf.png b/mkdocs/.cache/plugin/social/08c3137589ee1e07c6b82c5f3e9e47bf.png new file mode 100644 index 0000000..5215c38 Binary files /dev/null and b/mkdocs/.cache/plugin/social/08c3137589ee1e07c6b82c5f3e9e47bf.png differ diff --git a/mkdocs/.cache/plugin/social/1e5bfd318a5e9797b8831dbc973c0e57.png b/mkdocs/.cache/plugin/social/1e5bfd318a5e9797b8831dbc973c0e57.png new file mode 100644 index 0000000..26daf57 Binary files /dev/null and b/mkdocs/.cache/plugin/social/1e5bfd318a5e9797b8831dbc973c0e57.png differ diff --git a/mkdocs/.cache/plugin/social/2c4ddee96734cdcd028d11e87d09ac54.png b/mkdocs/.cache/plugin/social/2c4ddee96734cdcd028d11e87d09ac54.png new file mode 100644 index 0000000..4d94562 Binary files /dev/null and b/mkdocs/.cache/plugin/social/2c4ddee96734cdcd028d11e87d09ac54.png differ diff --git a/mkdocs/.cache/plugin/social/3f61be45dd5d8e9a1d4e6862e64b7214.png b/mkdocs/.cache/plugin/social/3f61be45dd5d8e9a1d4e6862e64b7214.png new file mode 100644 index 0000000..481d9fa Binary files /dev/null and b/mkdocs/.cache/plugin/social/3f61be45dd5d8e9a1d4e6862e64b7214.png differ diff --git a/mkdocs/.cache/plugin/social/42eea5e63f7af7504d3273126c270804.png b/mkdocs/.cache/plugin/social/42eea5e63f7af7504d3273126c270804.png new file mode 100644 index 0000000..31c3c68 Binary files /dev/null and b/mkdocs/.cache/plugin/social/42eea5e63f7af7504d3273126c270804.png differ diff --git a/mkdocs/.cache/plugin/social/4491c6079bc3398b69a84ade4d737edc.png b/mkdocs/.cache/plugin/social/4491c6079bc3398b69a84ade4d737edc.png new file mode 100644 index 0000000..afbbbe1 Binary files /dev/null and b/mkdocs/.cache/plugin/social/4491c6079bc3398b69a84ade4d737edc.png differ diff --git a/mkdocs/.cache/plugin/social/49f28fa8303f79b46bfb7904c8e551a1.png b/mkdocs/.cache/plugin/social/49f28fa8303f79b46bfb7904c8e551a1.png new file mode 100644 index 0000000..cc6851b Binary files /dev/null and b/mkdocs/.cache/plugin/social/49f28fa8303f79b46bfb7904c8e551a1.png differ diff --git a/mkdocs/.cache/plugin/social/5642de01e7f59764299bd2e8ed35a5d0.png b/mkdocs/.cache/plugin/social/5642de01e7f59764299bd2e8ed35a5d0.png new file mode 100644 index 0000000..6305b67 Binary files /dev/null and b/mkdocs/.cache/plugin/social/5642de01e7f59764299bd2e8ed35a5d0.png differ diff --git a/mkdocs/.cache/plugin/social/59a246ca1baf0f21e33a0f0a13e1fbd5.png b/mkdocs/.cache/plugin/social/59a246ca1baf0f21e33a0f0a13e1fbd5.png new file mode 100644 index 0000000..5fd1cda Binary files /dev/null and b/mkdocs/.cache/plugin/social/59a246ca1baf0f21e33a0f0a13e1fbd5.png differ diff --git a/mkdocs/.cache/plugin/social/5a026625721699a22ed4902c86e27264.png b/mkdocs/.cache/plugin/social/5a026625721699a22ed4902c86e27264.png new file mode 100644 index 0000000..6009e1f Binary files /dev/null and b/mkdocs/.cache/plugin/social/5a026625721699a22ed4902c86e27264.png differ diff --git a/mkdocs/.cache/plugin/social/630ed53169b0d638a0ecbc5a43b36dd5.png b/mkdocs/.cache/plugin/social/630ed53169b0d638a0ecbc5a43b36dd5.png new file mode 100644 index 0000000..d3b1a8a Binary files /dev/null and b/mkdocs/.cache/plugin/social/630ed53169b0d638a0ecbc5a43b36dd5.png differ diff --git a/mkdocs/.cache/plugin/social/75846f8ef2f495a7834e15cf35a558af.png b/mkdocs/.cache/plugin/social/75846f8ef2f495a7834e15cf35a558af.png new file mode 100644 index 0000000..d2cfff2 Binary files /dev/null and b/mkdocs/.cache/plugin/social/75846f8ef2f495a7834e15cf35a558af.png differ diff --git a/mkdocs/.cache/plugin/social/7cf40f902bff1e35d8f0d03034794e4a.png b/mkdocs/.cache/plugin/social/7cf40f902bff1e35d8f0d03034794e4a.png new file mode 100644 index 0000000..4345aff Binary files /dev/null and b/mkdocs/.cache/plugin/social/7cf40f902bff1e35d8f0d03034794e4a.png differ diff --git a/mkdocs/.cache/plugin/social/bbe91e9dff56613b08f6e23ca8196d35.png b/mkdocs/.cache/plugin/social/bbe91e9dff56613b08f6e23ca8196d35.png new file mode 100644 index 0000000..a2d7102 Binary files /dev/null and b/mkdocs/.cache/plugin/social/bbe91e9dff56613b08f6e23ca8196d35.png differ diff --git a/mkdocs/.cache/plugin/social/ca221d210444f7caca141f1462c1634d.png b/mkdocs/.cache/plugin/social/ca221d210444f7caca141f1462c1634d.png new file mode 100644 index 0000000..ea626c4 Binary files /dev/null and b/mkdocs/.cache/plugin/social/ca221d210444f7caca141f1462c1634d.png differ diff --git a/mkdocs/.cache/plugin/social/f380f2c14dd2d5339cbb8e757cc24fc9.png b/mkdocs/.cache/plugin/social/f380f2c14dd2d5339cbb8e757cc24fc9.png new file mode 100644 index 0000000..bf058b1 Binary files /dev/null and b/mkdocs/.cache/plugin/social/f380f2c14dd2d5339cbb8e757cc24fc9.png differ diff --git a/mkdocs/docs/adv/ansible.md b/mkdocs/docs/adv/ansible.md new file mode 100644 index 0000000..2a6433b --- /dev/null +++ b/mkdocs/docs/adv/ansible.md @@ -0,0 +1,509 @@ +# Setting Up Ansible with Tailscale for Remote Server Management + +## Overview + +This guide walks you through setting up Ansible to manage remote servers (like ThinkCentre units) using Tailscale for secure networking. This approach provides reliable remote access without complex port forwarding or VPN configurations. + +In plainer language; this allows you to manage several Changemaker nodes remotely. If you are a full time campaigner, this can enable you to manage several campaigns infrastructure from a central location while each user gets their own Changemaker box. + +## What You'll Learn + +- How to set up Ansible for infrastructure automation +- How to configure secure remote access using Tailscale +- How to troubleshoot common SSH and networking issues +- Why this approach is better than alternatives like Cloudflare Tunnels for simple SSH access + +## Prerequisites + +- **Master Node**: Your main computer running Ubuntu/Linux (control machine) +- **Target Nodes**: Remote servers/ThinkCentres running Ubuntu/Linux +- **Both machines**: Must have internet access +- **User Account**: Same username on all machines (recommended) + +## Part 1: Initial Setup on Master Node + +### 1. Create Ansible Directory Structure + +```bash +# Create project directory +mkdir ~/ansible_quickstart +cd ~/ansible_quickstart + +# Create directory structure +mkdir -p group_vars host_vars roles playbooks +``` + +### 2. Install Ansible + +```bash +sudo apt update +sudo apt install ansible +``` + +### 3. Generate SSH Keys (if not already done) + +```bash +# Generate SSH key pair +ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa + +# Display public key (save this for later) +cat ~/.ssh/id_rsa.pub +``` + +## Part 2: Target Node Setup (Physical Access Required Initially) + +### 1. Enable SSH on Target Node + +Access each target node physically (monitor + keyboard): + +```bash +# Update system +sudo apt update && sudo apt upgrade -y + +# Install and enable SSH +sudo apt install openssh-server +sudo systemctl enable ssh +sudo systemctl start ssh + +# Check SSH status +sudo systemctl status ssh +``` + +### 2. Configure SSH Key Authentication + +```bash +# Create .ssh directory +mkdir -p ~/.ssh +chmod 700 ~/.ssh + +# Create authorized_keys file +nano ~/.ssh/authorized_keys +``` + +Paste your public key from the master node, then: + +```bash +# Set proper permissions +chmod 600 ~/.ssh/authorized_keys +``` + +### 3. Configure SSH Security + +```bash +# Edit SSH config +sudo nano /etc/ssh/sshd_config +``` + +Ensure these lines are uncommented: + +``` +PubkeyAuthentication yes +AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 +``` + +```bash +# Restart SSH service +sudo systemctl restart ssh +``` + +### 4. Configure Firewall + +```bash +# Check firewall status +sudo ufw status + +# Allow SSH through firewall +sudo ufw allow ssh + +# Fix home directory permissions (required for SSH keys) +chmod 755 ~/ +``` + +## Part 3: Test Local SSH Connection + +Before proceeding with remote access, test SSH connectivity locally: + +```bash +# From master node, test SSH to target +ssh username@ +``` + +**Common Issues and Solutions:** + +- **Connection hangs**: Check firewall rules (`sudo ufw allow ssh`) +- **Permission denied**: Verify SSH keys and file permissions +- **SSH config errors**: Ensure `PubkeyAuthentication yes` is set + +## Part 4: Set Up Tailscale for Remote Access + +### Why Tailscale Over Alternatives + +We initially tried Cloudflare Tunnels but encountered complexity with: + +- DNS routing issues +- Complex configuration for SSH +- Same-network testing problems +- Multiple configuration approaches with varying success + +**Tailscale is superior because:** + +- Zero configuration mesh networking +- Works from any network +- Persistent IP addresses +- No port forwarding needed +- Free for personal use + +### 1. Install Tailscale on Master Node + +```bash +# Install Tailscale +curl -fsSL https://tailscale.com/install.sh | sh + +# Connect to Tailscale network +sudo tailscale up +``` + +Follow the authentication URL to connect with your Google/Microsoft/GitHub account. + +### 2. Install Tailscale on Target Nodes + +**On each target node:** + +```bash +# Install Tailscale +curl -fsSL https://tailscale.com/install.sh | sh + +# Connect to Tailscale network +sudo tailscale up +``` + +Authenticate each device through the provided URL. + +### 3. Get Tailscale IP Addresses + +**On each machine:** + +```bash +# Get your Tailscale IP +tailscale ip -4 +``` + +Each device receives a persistent IP like `100.x.x.x`. + +## Part 5: Configure Ansible + +### 1. Create Inventory File + +```bash +# Create inventory.ini +cd ~/ansible_quickstart +nano inventory.ini +``` + +**Content:** + +```ini +[thinkcenter] +tc-node1 ansible_host=100.x.x.x ansible_user=your-username +tc-node2 ansible_host=100.x.x.x ansible_user=your-username + +[all:vars] +ansible_ssh_private_key_file=~/.ssh/id_rsa +ansible_host_key_checking=False +``` + +Replace: + +- `100.x.x.x` with actual Tailscale IPs +- `your-username` with your actual username + +### 2. Test Ansible Connectivity + +```bash +# Test connection to all nodes +ansible all -i inventory.ini -m ping +``` + +**Expected output:** + +``` +tc-node1 | SUCCESS => { + "changed": false, + "ping": "pong" +} +``` + +## Part 6: Create and Run Playbooks + +### 1. Simple Information Gathering Playbook + +```bash +mkdir -p playbooks +nano playbooks/info-playbook.yml +``` + +**Content:** + +```yaml +--- +- name: Gather Node Information + hosts: all + tasks: + - name: Get system information + setup: + + - name: Display basic system info + debug: + msg: | + Hostname: {{ ansible_hostname }} + Operating System: {{ ansible_distribution }} {{ ansible_distribution_version }} + Architecture: {{ ansible_architecture }} + Memory: {{ ansible_memtotal_mb }}MB + CPU Cores: {{ ansible_processor_vcpus }} + + - name: Show disk usage + command: df -h / + register: disk_info + + - name: Display disk usage + debug: + msg: "Root filesystem usage: {{ disk_info.stdout_lines[1] }}" + + - name: Check uptime + command: uptime + register: uptime_info + + - name: Display uptime + debug: + msg: "System uptime: {{ uptime_info.stdout }}" +``` + +### 2. Run the Playbook + +```bash +ansible-playbook -i inventory.ini playbooks/info-playbook.yml +``` + +## Part 7: Advanced Playbook Example + +### System Setup Playbook + +```bash +nano playbooks/setup-node.yml +``` + +**Content:** + +```yaml +--- +- name: Setup ThinkCentre Node + hosts: all + become: yes + tasks: + - name: Update package cache + apt: + update_cache: yes + + - name: Install essential packages + package: + name: + - htop + - vim + - curl + - git + - docker.io + state: present + + - name: Add user to docker group + user: + name: "{{ ansible_user }}" + groups: docker + append: yes + + - name: Create management directory + file: + path: /opt/management + state: directory + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" +``` + +## Troubleshooting Guide + +### SSH Issues + +**Problem: SSH connection hangs** + +- Check firewall: `sudo ufw status` and `sudo ufw allow ssh` +- Verify SSH service: `sudo systemctl status ssh` +- Test local connectivity first + +**Problem: Permission denied (publickey)** + +- Check SSH key permissions: `chmod 600 ~/.ssh/authorized_keys` +- Verify home directory permissions: `chmod 755 ~/` +- Ensure SSH config allows key auth: `PubkeyAuthentication yes` + +**Problem: Bad owner or permissions on SSH config** + +```bash +chmod 600 ~/.ssh/config +``` + +### Ansible Issues + +**Problem: Host key verification failed** + +- Add to inventory: `ansible_host_key_checking=False` + +**Problem: Ansible command not found** + +```bash +sudo apt install ansible +``` + +**Problem: Connection timeouts** + +- Verify Tailscale connectivity: `ping ` +- Check if both nodes are connected: `tailscale status` + +### Tailscale Issues + +**Problem: Can't connect to Tailscale IP** + +- Verify both devices are authenticated: `tailscale status` +- Check Tailscale is running: `sudo systemctl status tailscaled` +- Restart Tailscale: `sudo tailscale up` + +## Scaling to Multiple Nodes + +### Adding New Nodes + +1. **Install Tailscale on new node** +2. **Set up SSH access** (repeat Part 2) +3. **Add to inventory.ini:** + +```ini +[thinkcenter] +tc-node1 ansible_host=100.125.148.60 ansible_user=bunker-admin +tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin +tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin +``` + +### Group Management + +```ini +[webservers] +tc-node1 ansible_host=100.x.x.x ansible_user=bunker-admin +tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin + +[databases] +tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin + +[all:vars] +ansible_ssh_private_key_file=~/.ssh/id_rsa +ansible_host_key_checking=False +``` + +Run playbooks on specific groups: + +```bash +ansible-playbook -i inventory.ini -l webservers playbook.yml +``` + +## Best Practices + +### Security + +- Use SSH keys, not passwords +- Keep Tailscale client updated +- Regular security updates via Ansible +- Use `become: yes` only when necessary + +### Organization + +``` +ansible_quickstart/ +├── inventory.ini +├── group_vars/ +├── host_vars/ +├── roles/ +└── playbooks/ + ├── info-playbook.yml + ├── setup-node.yml + └── maintenance.yml +``` + +### Monitoring and Maintenance + +Create regular maintenance playbooks: + +```yaml +- name: System maintenance + hosts: all + become: yes + tasks: + - name: Update all packages + apt: + upgrade: dist + update_cache: yes + + - name: Clean package cache + apt: + autoclean: yes + autoremove: yes +``` + +## Alternative Approaches We Considered + +### Cloudflare Tunnels + +- **Pros**: Good for web services, handles NAT traversal +- **Cons**: Complex SSH setup, DNS routing issues, same-network problems +- **Use case**: Better for web applications than SSH access + +### Traditional VPN + +- **Pros**: Full network access +- **Cons**: Complex setup, port forwarding required, router configuration +- **Use case**: When you control the network infrastructure + +### SSH Reverse Tunnels + +- **Pros**: Simple concept +- **Cons**: Requires VPS, single point of failure, manual setup +- **Use case**: Temporary access or when other methods fail + +## Conclusion + +This setup provides: + +- **Reliable remote access** from anywhere +- **Secure mesh networking** with Tailscale +- **Infrastructure automation** with Ansible +- **Easy scaling** to multiple nodes +- **No complex networking** required + +The combination of Ansible + Tailscale is ideal for managing distributed infrastructure without the complexity of traditional VPN setups or the limitations of cloud-specific solutions. + +## Quick Reference Commands + +```bash +# Check Tailscale status +tailscale status + +# Test Ansible connectivity +ansible all -i inventory.ini -m ping + +# Run playbook on all hosts +ansible-playbook -i inventory.ini playbook.yml + +# Run playbook on specific group +ansible-playbook -i inventory.ini -l groupname playbook.yml + +# Run single command on all hosts +ansible all -i inventory.ini -m command -a "uptime" + +# SSH to node via Tailscale +ssh username@100.x.x.x +``` \ No newline at end of file diff --git a/mkdocs/docs/adv/index.md b/mkdocs/docs/adv/index.md new file mode 100644 index 0000000..45dcf97 --- /dev/null +++ b/mkdocs/docs/adv/index.md @@ -0,0 +1,3 @@ +# Advanced Configurations + +We are also publishing how BNKops does several advanced workflows. These include things like assembling hardware, how to manage a network, how to manage several changemakers simultaneously, and integrating AI. \ No newline at end of file diff --git a/mkdocs/docs/adv/vscode-ssh.md b/mkdocs/docs/adv/vscode-ssh.md new file mode 100644 index 0000000..5bc962a --- /dev/null +++ b/mkdocs/docs/adv/vscode-ssh.md @@ -0,0 +1,676 @@ +# Remote Development with VSCode over Tailscale + +## Overview + +This guide shows you how to set up Visual Studio Code for remote development on your servers using the Tailscale network. This allows you to develop directly on your remote ThinkCentre units as if they were local machines, with full access to files, terminals, and debugging capabilities. + +## What You'll Learn + +- How to configure VSCode for remote SSH connections +- How to set up remote development environments +- How to manage multiple remote servers efficiently +- How to troubleshoot common remote development issues +- Best practices for remote development workflows + +## Prerequisites + +- **Completed the Ansible + Tailscale setup** from the previous guide +- **VSCode installed** on your local machine (master node) +- **Working SSH access** to remote servers via Tailscale +- **Tailscale running** on both local and remote machines + +## Verify Prerequisites + +Before starting, ensure your setup is working: + +```bash +# Check Tailscale connectivity +tailscale status + +# Test SSH access +ssh bunker-admin@100.125.148.60 + +# Check VSCode is installed +code --version +``` + +## Part 1: Install and Configure Remote-SSH Extension + +### 1. Install the Remote Development Extensions + +**Option A: Install Remote Development Pack (Recommended)** +1. Open VSCode +2. Press **Ctrl+Shift+X** (or **Cmd+Shift+X** on Mac) +3. Search for **"Remote Development"** +4. Install the **Remote Development extension pack** by Microsoft + +This pack includes: +- Remote - SSH +- Remote - SSH: Editing Configuration Files +- Remote - Containers +- Remote - WSL (Windows only) + +**Option B: Install Individual Extension** +1. Search for **"Remote - SSH"** +2. Install **Remote - SSH** by Microsoft + +### 2. Verify Installation + +After installation, you should see: +- Remote Explorer icon in the Activity Bar (left sidebar) +- "Remote-SSH" commands in Command Palette (Ctrl+Shift+P) + +## Part 2: Configure SSH Connections + +### 1. Access SSH Configuration + +**Method A: Through VSCode** +1. Press **Ctrl+Shift+P** to open Command Palette +2. Type **"Remote-SSH: Open SSH Configuration File..."** +3. Select your SSH config file (usually the first option) + +**Method B: Direct File Editing** +```bash +# Edit SSH config file directly +nano ~/.ssh/config +``` + +### 2. Add Server Configurations + +Add your servers to the SSH config file: + +``` +# Primary ThinkCentre Node +Host tc-node1 + HostName 100.125.148.60 + User bunker-admin + IdentityFile ~/.ssh/id_rsa + ForwardAgent yes + ServerAliveInterval 60 + ServerAliveCountMax 3 + +# Additional nodes (add as needed) +Host tc-node2 + HostName 100.x.x.x + User bunker-admin + IdentityFile ~/.ssh/id_rsa + ForwardAgent yes + ServerAliveInterval 60 + ServerAliveCountMax 3 + +Host tc-node3 + HostName 100.x.x.x + User bunker-admin + IdentityFile ~/.ssh/id_rsa + ForwardAgent yes + ServerAliveInterval 60 + ServerAliveCountMax 3 +``` + +**Configuration Options Explained:** +- `Host`: Friendly name for the connection +- `HostName`: Tailscale IP address +- `User`: Username on the remote server +- `IdentityFile`: Path to your SSH private key +- `ForwardAgent`: Enables SSH agent forwarding for Git operations +- `ServerAliveInterval`: Keeps connection alive (prevents timeouts) +- `ServerAliveCountMax`: Number of keepalive attempts + +### 3. Set Proper SSH Key Permissions + +```bash +# Ensure SSH config has correct permissions +chmod 600 ~/.ssh/config + +# Verify SSH key permissions +chmod 600 ~/.ssh/id_rsa +chmod 644 ~/.ssh/id_rsa.pub +``` + +## Part 3: Connect to Remote Servers + +### 1. Connect via Command Palette + +1. Press **Ctrl+Shift+P** +2. Type **"Remote-SSH: Connect to Host..."** +3. Select your server (e.g., `tc-node1`) +4. VSCode will open a new window connected to the remote server + +### 2. Connect via Remote Explorer + +1. Click the **Remote Explorer** icon in Activity Bar +2. Expand **SSH Targets** +3. Click the **connect** icon next to your server name + +### 3. Connect via Quick Menu + +1. Click the **remote indicator** in bottom-left corner (looks like ><) +2. Select **"Connect to Host..."** +3. Choose your server from the list + +### 4. First Connection Process + +On first connection, VSCode will: +1. **Verify the host key** (click "Continue" if prompted) +2. **Install VSCode Server** on the remote machine (automatic) +3. **Open a remote window** with access to the remote file system + +**Expected Timeline:** +- First connection: 1-3 minutes (installs VSCode Server) +- Subsequent connections: 10-30 seconds + +## Part 4: Remote Development Environment Setup + +### 1. Open Remote Workspace + +Once connected: + +```bash +# In the VSCode terminal (now running on remote server) +# Navigate to your project +cd /home/bunker-admin/projects + +# Open current directory in VSCode +code . + +# Or open a specific project +code /opt/myproject +``` + +### 2. Install Extensions on Remote Server + +Extensions need to be installed separately on the remote server: + +**Essential Development Extensions:** +1. **Python** (Microsoft) - Python development +2. **GitLens** (GitKraken) - Enhanced Git capabilities +3. **Docker** (Microsoft) - Container development +4. **Prettier** - Code formatting +5. **ESLint** - JavaScript linting +6. **Auto Rename Tag** - HTML/XML tag editing + +**To Install:** +1. Go to Extensions (Ctrl+Shift+X) +2. Find your desired extension +3. Click **"Install in SSH: tc-node1"** (not local install) + +### 3. Configure Git on Remote Server + +```bash +# In VSCode terminal (remote) +git config --global user.name "Your Name" +git config --global user.email "your.email@example.com" + +# Test Git connectivity +git clone https://github.com/yourusername/yourrepo.git +``` + +## Part 5: Remote Development Workflows + +### 1. File Management + +**File Explorer:** +- Shows remote server's file system +- Create, edit, delete files directly +- Drag and drop between local and remote (limited) + +**File Transfer:** +```bash +# Upload files to remote (from local terminal) +scp localfile.txt bunker-admin@100.125.148.60:/home/bunker-admin/ + +# Download files from remote +scp bunker-admin@100.125.148.60:/remote/path/file.txt ./local/path/ +``` + +### 2. Terminal Usage + +**Integrated Terminal:** +- Press **Ctrl+`** to open terminal +- Runs directly on remote server +- Multiple terminals supported +- Full shell access (bash, zsh, etc.) + +**Common Remote Terminal Commands:** +```bash +# Check system resources +htop +df -h +free -h + +# Install packages +sudo apt update +sudo apt install nodejs npm + +# Start services +sudo systemctl start nginx +sudo docker-compose up -d +``` + +### 3. Port Forwarding + +**Automatic Port Forwarding:** +VSCode automatically detects and forwards common development ports. + +**Manual Port Forwarding:** +1. Open **Ports** tab in terminal panel +2. Click **"Forward a Port"** +3. Enter port number (e.g., 3000, 8080, 5000) +4. Access via `http://localhost:port` on local machine + +**Example: Web Development** +```bash +# Start a web server on remote (port 3000) +npm start + +# VSCode automatically suggests forwarding port 3000 +# Access at http://localhost:3000 on your local machine +``` + +### 4. Debugging Remote Applications + +**Python Debugging:** +```json +// .vscode/launch.json on remote server +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + } + ] +} +``` + +**Node.js Debugging:** +```json +// .vscode/launch.json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Program", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/app.js" + } + ] +} +``` + +## Part 6: Advanced Configuration + +### 1. Workspace Settings + +Create remote-specific settings: + +```json +// .vscode/settings.json (on remote server) +{ + "python.defaultInterpreterPath": "/usr/bin/python3", + "terminal.integrated.shell.linux": "/bin/bash", + "files.autoSave": "afterDelay", + "editor.formatOnSave": true, + "remote.SSH.remotePlatform": { + "tc-node1": "linux" + } +} +``` + +### 2. Multi-Server Management + +**Switch Between Servers:** +1. Click remote indicator (bottom-left) +2. Select **"Connect to Host..."** +3. Choose different server + +**Compare Files Across Servers:** +1. Open file from server A +2. Connect to server B in new window +3. Open corresponding file +4. Use **"Compare with..."** command + +### 3. Sync Configuration + +**Settings Sync:** +1. Enable Settings Sync in VSCode +2. Settings, extensions, and keybindings sync to remote +3. Consistent experience across all servers + +## Part 7: Project-Specific Setups + +### 1. Python Development + +```bash +# On remote server +# Create virtual environment +python3 -m venv venv +source venv/bin/activate + +# Install packages +pip install flask django requests + +# VSCode automatically detects Python interpreter +``` + +**VSCode Python Configuration:** +```json +// .vscode/settings.json +{ + "python.defaultInterpreterPath": "./venv/bin/python", + "python.linting.enabled": true, + "python.linting.pylintEnabled": true +} +``` + +### 2. Node.js Development + +```bash +# On remote server +# Install Node.js +curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - +sudo apt-get install -y nodejs + +# Create project +mkdir myapp && cd myapp +npm init -y +npm install express +``` + +### 3. Docker Development + +```bash +# On remote server +# Install Docker (if not already done via Ansible) +sudo apt install docker.io docker-compose +sudo usermod -aG docker $USER + +# Create Dockerfile +cat > Dockerfile << EOF +FROM node:18 +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +EXPOSE 3000 +CMD ["npm", "start"] +EOF +``` + +**VSCode Docker Integration:** +- Install Docker extension on remote +- Right-click Dockerfile → "Build Image" +- Manage containers from VSCode interface + +## Part 8: Troubleshooting Guide + +### Common Connection Issues + +**Problem: "Could not establish connection to remote host"** + +**Solutions:** +```bash +# Check Tailscale connectivity +tailscale status +ping 100.125.148.60 + +# Test SSH manually +ssh bunker-admin@100.125.148.60 + +# Check SSH config syntax +ssh -T tc-node1 +``` + +**Problem: "Permission denied (publickey)"** + +**Solutions:** +```bash +# Check SSH key permissions +chmod 600 ~/.ssh/id_rsa +chmod 600 ~/.ssh/config + +# Verify SSH agent +ssh-add ~/.ssh/id_rsa +ssh-add -l + +# Test SSH connection verbosely +ssh -v bunker-admin@100.125.148.60 +``` + +**Problem: "Host key verification failed"** + +**Solutions:** +```bash +# Remove old host key +ssh-keygen -R 100.125.148.60 + +# Or disable host key checking (less secure) +# Add to SSH config: +# StrictHostKeyChecking no +``` + +### VSCode-Specific Issues + +**Problem: Extensions not working on remote** + +**Solutions:** +1. Install extensions specifically for remote server +2. Check extension compatibility with remote development +3. Reload VSCode window: Ctrl+Shift+P → "Developer: Reload Window" + +**Problem: Slow performance** + +**Solutions:** +- Use `.vscode/settings.json` to exclude large directories: +```json +{ + "files.watcherExclude": { + "**/node_modules/**": true, + "**/.git/objects/**": true, + "**/dist/**": true + } +} +``` + +**Problem: Terminal not starting** + +**Solutions:** +```bash +# Check shell path in remote settings +"terminal.integrated.shell.linux": "/bin/bash" + +# Or let VSCode auto-detect +"terminal.integrated.defaultProfile.linux": "bash" +``` + +### Network and Performance Issues + +**Problem: Connection timeouts** + +**Solutions:** +Add to SSH config: +``` +ServerAliveInterval 60 +ServerAliveCountMax 3 +TCPKeepAlive yes +``` + +**Problem: File transfer slow** + +**Solutions:** +- Use `.vscodeignore` to exclude unnecessary files +- Compress large files before transfer +- Use `rsync` for large file operations: +```bash +rsync -avz --progress localdir/ bunker-admin@100.125.148.60:remotedir/ +``` + +## Part 9: Best Practices + +### Security Best Practices + +1. **Use SSH keys, never passwords** +2. **Keep SSH agent secure** +3. **Regular security updates on remote servers** +4. **Use VSCode's secure connection verification** + +### Performance Optimization + +1. **Exclude unnecessary files**: +```json +// .vscode/settings.json +{ + "files.watcherExclude": { + "**/node_modules/**": true, + "**/.git/**": true, + "**/dist/**": true, + "**/build/**": true + }, + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/*.code-search": true + } +} +``` + +2. **Use remote workspace for large projects** +3. **Close unnecessary windows and extensions** +4. **Use efficient development workflows** + +### Development Workflow + +1. **Use version control effectively**: +```bash +# Always work in Git repositories +git status +git add . +git commit -m "feature: add new functionality" +git push origin main +``` + +2. **Environment separation**: +```bash +# Development +ssh tc-node1 +cd /home/bunker-admin/dev-projects + +# Production +ssh tc-node2 +cd /opt/production-apps +``` + +3. **Backup important work**: +```bash +# Regular backups via Git +git push origin main + +# Or manual backup +scp -r bunker-admin@100.125.148.60:/important/project ./backup/ +``` + +## Part 10: Team Collaboration + +### Shared Development Servers + +**SSH Config for Team:** +``` +# Shared development server +Host team-dev + HostName 100.x.x.x + User dev-user + IdentityFile ~/.ssh/team_dev_key + ForwardAgent yes + +# Personal development +Host my-dev + HostName 100.125.148.60 + User bunker-admin + IdentityFile ~/.ssh/id_rsa +``` + +### Project Structure + +``` +/opt/projects/ +├── project-a/ +│ ├── dev/ # Development branch +│ ├── staging/ # Staging environment +│ └── docs/ # Documentation +├── project-b/ +└── shared-tools/ # Common utilities +``` + +### Access Management + +```bash +# Create shared project directory +sudo mkdir -p /opt/projects +sudo chown -R :developers /opt/projects +sudo chmod -R g+w /opt/projects + +# Add users to developers group +sudo usermod -a -G developers bunker-admin +``` + +## Quick Reference + +### Essential VSCode Remote Commands + +```bash +# Command Palette shortcuts +Ctrl+Shift+P → "Remote-SSH: Connect to Host..." +Ctrl+Shift+P → "Remote-SSH: Open SSH Configuration File..." +Ctrl+Shift+P → "Remote-SSH: Kill VS Code Server on Host..." + +# Terminal +Ctrl+` → Open integrated terminal +Ctrl+Shift+` → Create new terminal + +# File operations +Ctrl+O → Open file +Ctrl+S → Save file +Ctrl+Shift+E → Focus file explorer +``` + +### SSH Connection Quick Test + +```bash +# Test connectivity +ssh -T tc-node1 + +# Connect with verbose output +ssh -v bunker-admin@100.125.148.60 + +# Check SSH config +ssh -F ~/.ssh/config tc-node1 +``` + +### Port Forwarding Commands + +```bash +# Manual port forwarding +ssh -L 3000:localhost:3000 bunker-admin@100.125.148.60 + +# Background tunnel +ssh -f -N -L 8080:localhost:80 bunker-admin@100.125.148.60 +``` + +## Conclusion + +This remote development setup provides: + +- **Full development environment** on remote servers +- **Seamless file access** and editing capabilities +- **Integrated debugging** and terminal access +- **Port forwarding** for web development +- **Extension ecosystem** available remotely +- **Secure connections** through Tailscale network + +The combination of VSCode Remote Development with Tailscale networking creates a powerful, flexible development environment that works from anywhere while maintaining security and performance. + +Whether you're developing Python applications, Node.js services, or managing Docker containers, this setup provides a professional remote development experience that rivals local development while leveraging the power and resources of your remote servers. \ No newline at end of file diff --git a/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json b/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json index f409dbc..5333f7d 100644 --- a/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json +++ b/mkdocs/docs/assets/repo-data/admin-changemaker.lite.json @@ -6,11 +6,11 @@ "language": "HTML", "stars_count": 0, "forks_count": 0, - "open_issues_count": 0, - "updated_at": "2025-06-30T21:38:32-06:00", + "open_issues_count": 1, + "updated_at": "2025-07-01T09:33:43-06:00", "created_at": "2025-05-28T14:54:59-06:00", "clone_url": "https://gitea.bnkops.com/admin/changemaker.lite.git", "ssh_url": "git@gitea.bnkops.com:admin/changemaker.lite.git", "default_branch": "main", - "last_build_update": "2025-06-30T21:38:32-06:00" + "last_build_update": "2025-07-01T09:33:43-06:00" } \ No newline at end of file diff --git a/mkdocs/docs/assets/repo-data/anthropics-claude-code.json b/mkdocs/docs/assets/repo-data/anthropics-claude-code.json new file mode 100644 index 0000000..518e62f --- /dev/null +++ b/mkdocs/docs/assets/repo-data/anthropics-claude-code.json @@ -0,0 +1,16 @@ +{ + "full_name": "anthropics/claude-code", + "name": "claude-code", + "description": "Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.", + "html_url": "https://github.com/anthropics/claude-code", + "language": "Shell", + "stars_count": 16934, + "forks_count": 929, + "open_issues_count": 1495, + "updated_at": "2025-07-02T17:38:19Z", + "created_at": "2025-02-22T17:41:21Z", + "clone_url": "https://github.com/anthropics/claude-code.git", + "ssh_url": "git@github.com:anthropics/claude-code.git", + "default_branch": "main", + "last_build_update": "2025-07-02T16:32:38Z" +} \ No newline at end of file diff --git a/mkdocs/docs/assets/repo-data/coder-code-server.json b/mkdocs/docs/assets/repo-data/coder-code-server.json index 3e3c526..c0c12d7 100644 --- a/mkdocs/docs/assets/repo-data/coder-code-server.json +++ b/mkdocs/docs/assets/repo-data/coder-code-server.json @@ -4,10 +4,10 @@ "description": "VS Code in the browser", "html_url": "https://github.com/coder/code-server", "language": "TypeScript", - "stars_count": 72508, - "forks_count": 6062, - "open_issues_count": 142, - "updated_at": "2025-07-01T15:16:52Z", + "stars_count": 72530, + "forks_count": 6064, + "open_issues_count": 143, + "updated_at": "2025-07-02T17:11:14Z", "created_at": "2019-02-27T16:50:41Z", "clone_url": "https://github.com/coder/code-server.git", "ssh_url": "git@github.com:coder/code-server.git", diff --git a/mkdocs/docs/assets/repo-data/gethomepage-homepage.json b/mkdocs/docs/assets/repo-data/gethomepage-homepage.json index d01b936..735b307 100644 --- a/mkdocs/docs/assets/repo-data/gethomepage-homepage.json +++ b/mkdocs/docs/assets/repo-data/gethomepage-homepage.json @@ -4,13 +4,13 @@ "description": "A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.", "html_url": "https://github.com/gethomepage/homepage", "language": "JavaScript", - "stars_count": 24583, - "forks_count": 1519, + "stars_count": 24608, + "forks_count": 1520, "open_issues_count": 1, - "updated_at": "2025-07-01T15:20:04Z", + "updated_at": "2025-07-02T17:20:41Z", "created_at": "2022-08-24T07:29:42Z", "clone_url": "https://github.com/gethomepage/homepage.git", "ssh_url": "git@github.com:gethomepage/homepage.git", "default_branch": "dev", - "last_build_update": "2025-07-01T12:14:06Z" + "last_build_update": "2025-07-02T12:13:57Z" } \ No newline at end of file diff --git a/mkdocs/docs/assets/repo-data/go-gitea-gitea.json b/mkdocs/docs/assets/repo-data/go-gitea-gitea.json index e96b370..915ed37 100644 --- a/mkdocs/docs/assets/repo-data/go-gitea-gitea.json +++ b/mkdocs/docs/assets/repo-data/go-gitea-gitea.json @@ -4,13 +4,13 @@ "description": "Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD", "html_url": "https://github.com/go-gitea/gitea", "language": "Go", - "stars_count": 49327, - "forks_count": 5887, - "open_issues_count": 2706, - "updated_at": "2025-07-01T14:28:19Z", + "stars_count": 49339, + "forks_count": 5891, + "open_issues_count": 2711, + "updated_at": "2025-07-02T16:36:32Z", "created_at": "2016-11-01T02:13:26Z", "clone_url": "https://github.com/go-gitea/gitea.git", "ssh_url": "git@github.com:go-gitea/gitea.git", "default_branch": "main", - "last_build_update": "2025-07-01T13:44:05Z" + "last_build_update": "2025-07-02T00:37:56Z" } \ No newline at end of file diff --git a/mkdocs/docs/assets/repo-data/knadh-listmonk.json b/mkdocs/docs/assets/repo-data/knadh-listmonk.json index 184a06c..1ca3439 100644 --- a/mkdocs/docs/assets/repo-data/knadh-listmonk.json +++ b/mkdocs/docs/assets/repo-data/knadh-listmonk.json @@ -4,10 +4,10 @@ "description": "High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.", "html_url": "https://github.com/knadh/listmonk", "language": "Go", - "stars_count": 17242, - "forks_count": 1657, - "open_issues_count": 104, - "updated_at": "2025-07-01T14:26:50Z", + "stars_count": 17248, + "forks_count": 1658, + "open_issues_count": 105, + "updated_at": "2025-07-02T10:32:44Z", "created_at": "2019-06-26T05:08:39Z", "clone_url": "https://github.com/knadh/listmonk.git", "ssh_url": "git@github.com:knadh/listmonk.git", diff --git a/mkdocs/docs/assets/repo-data/n8n-io-n8n.json b/mkdocs/docs/assets/repo-data/n8n-io-n8n.json index 11ee4cb..3480f52 100644 --- a/mkdocs/docs/assets/repo-data/n8n-io-n8n.json +++ b/mkdocs/docs/assets/repo-data/n8n-io-n8n.json @@ -4,13 +4,13 @@ "description": "Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.", "html_url": "https://github.com/n8n-io/n8n", "language": "TypeScript", - "stars_count": 113903, - "forks_count": 33364, - "open_issues_count": 1058, - "updated_at": "2025-07-01T15:22:32Z", + "stars_count": 114294, + "forks_count": 33577, + "open_issues_count": 1070, + "updated_at": "2025-07-02T17:42:44Z", "created_at": "2019-06-22T09:24:21Z", "clone_url": "https://github.com/n8n-io/n8n.git", "ssh_url": "git@github.com:n8n-io/n8n.git", "default_branch": "master", - "last_build_update": "2025-07-01T15:23:16Z" + "last_build_update": "2025-07-02T17:17:32Z" } \ No newline at end of file diff --git a/mkdocs/docs/assets/repo-data/nocodb-nocodb.json b/mkdocs/docs/assets/repo-data/nocodb-nocodb.json index d270c13..08cbf57 100644 --- a/mkdocs/docs/assets/repo-data/nocodb-nocodb.json +++ b/mkdocs/docs/assets/repo-data/nocodb-nocodb.json @@ -4,13 +4,13 @@ "description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 Open Source Airtable Alternative", "html_url": "https://github.com/nocodb/nocodb", "language": "TypeScript", - "stars_count": 55480, - "forks_count": 3987, - "open_issues_count": 714, - "updated_at": "2025-07-01T14:03:05Z", + "stars_count": 55505, + "forks_count": 3994, + "open_issues_count": 718, + "updated_at": "2025-07-02T17:05:35Z", "created_at": "2017-10-29T18:51:48Z", "clone_url": "https://github.com/nocodb/nocodb.git", "ssh_url": "git@github.com:nocodb/nocodb.git", "default_branch": "develop", - "last_build_update": "2025-07-01T14:26:19Z" + "last_build_update": "2025-07-02T16:01:20Z" } \ No newline at end of file diff --git a/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json b/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json index de092a5..59332e8 100644 --- a/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json +++ b/mkdocs/docs/assets/repo-data/squidfunk-mkdocs-material.json @@ -4,13 +4,13 @@ "description": "Documentation that simply works", "html_url": "https://github.com/squidfunk/mkdocs-material", "language": "Python", - "stars_count": 23763, - "forks_count": 3786, - "open_issues_count": 4, - "updated_at": "2025-07-01T13:38:53Z", + "stars_count": 23785, + "forks_count": 3787, + "open_issues_count": 5, + "updated_at": "2025-07-02T17:21:29Z", "created_at": "2016-01-28T22:09:23Z", "clone_url": "https://github.com/squidfunk/mkdocs-material.git", "ssh_url": "git@github.com:squidfunk/mkdocs-material.git", "default_branch": "master", - "last_build_update": "2025-07-01T12:56:28Z" + "last_build_update": "2025-07-02T16:12:25Z" } \ No newline at end of file diff --git a/mkdocs/docs/build/index.md b/mkdocs/docs/build/index.md index 608f005..14c0505 100644 --- a/mkdocs/docs/build/index.md +++ b/mkdocs/docs/build/index.md @@ -68,7 +68,7 @@ Before we dive into the technical setup, let's be clear about what you're doing - **Ubuntu 24.04 LTS (Noble Numbat)** - Recommended and tested !!! note "Getting Started on Ubunut" - Want some help getting started with a baseline buildout for a Ubunut server? You can use our [BNKops Server Build Script](./build-server.md) + Want some help getting started with a baseline buildout for a Ubunut server? You can use our [BNKops Server Build Script](./server.md) - Other Linux distributions with systemd support - WSL2 on Windows (limited functionality) @@ -90,7 +90,7 @@ Before we dive into the technical setup, let's be clear about what you're doing ### Software Prerequisites !!! tip "Getting Started on Docker" - Want some help getting started with a baseline buildout for a Ubunutu server? You can use our [BNKops Server Build Script](./build-server.md) to roll out a configured server in about 20 mins! + Want some help getting started with a baseline buildout for a Ubunutu server? You can use our [BNKops Server Build Script](./server.md) to roll out a configured server in about 20 mins! 1. **Docker Engine** (24.0+) diff --git a/mkdocs/docs/build/map.md b/mkdocs/docs/build/map.md index 45131d4..22be901 100644 --- a/mkdocs/docs/build/map.md +++ b/mkdocs/docs/build/map.md @@ -10,9 +10,13 @@ Map is BNKops canvassing application. It is built from the ground up to serve ou ## NocoDB Table Setup ### Required Columns + +!!! warning "Case Sensitive" + When entering in the required columns, make sure that you enter in exact information. Case sensitivity matters for mapping the values to the map itself. + Create a table in NocoDB with these required columns. The format here is the `Name of the column - column type - details`: -1. **Geo Location** (geo-data) - Format: "latitude;longitude" +1. **Geo-Location** (geo-data) - Format: "latitude;longitude" 2. **latitude** (Decimal) - Precision: 10, Scale: 8 3. **longitude** (Decimal) - Precision: 11, Scale: 8 diff --git a/mkdocs/docs/build/build-server.md b/mkdocs/docs/build/server.md similarity index 95% rename from mkdocs/docs/build/build-server.md rename to mkdocs/docs/build/server.md index 7c2cc0a..447d8f0 100644 --- a/mkdocs/docs/build/build-server.md +++ b/mkdocs/docs/build/server.md @@ -136,7 +136,9 @@ Login to Cloudflare cloudflared login ``` ### Configuration -- Setting up the [[service.cloudflared]] enables your cloudflared tunnel to automatically run on reboot + +The `./config.sh` and `./start-production.sh` scripts will properly configure a Cloudflare tunnel and service to put your system online. More info in the [Cloudflare Configuration.](../config/cloudflare-config.md) + ## [Pandoc](https://pandoc.org/) If you need to convert files from one markup format into another, pandoc is your swiss-army knife. diff --git a/mkdocs/docs/build/site.md b/mkdocs/docs/build/site.md new file mode 100644 index 0000000..82bdd5b --- /dev/null +++ b/mkdocs/docs/build/site.md @@ -0,0 +1,98 @@ +# Building the Site with MkDocs Material + +Welcome! This guide will help you get started building and customizing your site using [MkDocs Material](https://squidfunk.github.io/mkdocs-material/). + +--- + +## 🚀 How to Build Your Site (Step by Step) + +1. **Open your Coder instance.** + For example: coder.yourdomain.com +2. **Go to the mkdocs folder:** + In the terminal (for a new terminal press Crtl - Shift - ~), type: + ```sh + cd mkdocs + ``` +3. **Build the site:** + Type: + ```sh + mkdocs build + ``` + This creates the static website from your documents and places them in the `mkdocs/site` directory. + +**Preview your site locally:** + Visit [localhost:4000](localhost:4000) for local development or `live.youdomain.com` to see a public live load. + +- All documentation in the `mkdocs/docs` folder is included automatically. +- The site uses the beautiful and easy-to-use Material for MkDocs theme. + +[Material for MkDocs Documentation :material-arrow-right:](https://squidfunk.github.io/mkdocs-material/){ .md-button } + +!!! note "Build vs Serve" + Your website is built in stages. Any edits to documents in the mkdocs directory are instantly served and visible at [localhost:4000](localhost:4000) or if in production mode live.yourdomain.com. **The live site is not meant as a public access point and will crash if too many requests are made to it**. + + Running `mkdocs build` pushes any changes to the `site` directory, which then a ngnix server pushes them to the production server for public access at your root domain (yourdomain.com). + + You can think of it as serve/live = draft for personal review and build = save/push to production for the public. + + This combination allows for rapid development of documentation while ensuring your live site does not get updated until your content is ready. + +--- + +## 🧹 Resetting the Site + +If you want to start fresh: + +1. **Delete all folders EXCEPT these folders:** + - `/blog` + - `/javascripts` + - `/hooks` + - `/assets` + - `/stylesheets` + - `/overrides` + +2. **Reset the landing page:** + - Open the main `index.md` file and remove everything at the very top (the "front matter"). + - *Or* edit `/overrides/home.html` to change the landing page. + +3. **Reset the `mkdocs.yml`** + - Open `mkdocs.yml` and delete the `nav` section entirely. + - This action will enable mkdocs to build your site navigation based on file names in the root directory. + +--- + +## 🤖 Using AI to Help Build Your Site + +- If you have a [claude.ai](https://claude.ai/) subscription, you can use powerful AI in your Coder terminal to write or rewrite pages, including a new `home.html`. +- All you need to do is open the terminal and type: + ```sh + claude + ``` +- You can also try local AI tools like [Ollama](https://ollama.com/) for on-demand help. + +--- + +## 🛠️ First-Time Setup Tips + +- **Navigation:** + Open `mkdocs.yml` and remove the `nav` section to start with a blank menu. Add your own pages as you go. +- **Customize the look:** + Check out the [Material for MkDocs customization guide](https://squidfunk.github.io/mkdocs-material/setup/changing-the-theme/). +- **Live preview:** + Use `mkdocs serve` (see above) to see changes instantly as you edit. +- **Custom files:** + Put your own CSS, JavaScript, or HTML in `/assets`, `/stylesheets`, `/javascripts`, or `/overrides`. + +[Quick Start Guide :material-arrow-right:](https://squidfunk.github.io/mkdocs-material/creating-your-site/){ .md-button } + +--- + +## 📚 More Resources + +- [MkDocs User Guide :material-arrow-right:](https://www.mkdocs.org/user-guide/){ .md-button } +- [Material for MkDocs Features :material-arrow-right:](https://squidfunk.github.io/mkdocs-material/setup/){ .md-button } +- [BNKops MKdocs Configuration & Customization](../config/mkdocs.md){ .md-button } + +--- + +Happy building! diff --git a/mkdocs/docs/config/coder.md b/mkdocs/docs/config/coder.md new file mode 100644 index 0000000..8af8ee3 --- /dev/null +++ b/mkdocs/docs/config/coder.md @@ -0,0 +1,113 @@ +# Coder Configuration + +This section describes the configuration and features of the code-server environment. + +## Accessing Code Server + +- **URL:** `http://localhost:8080` +- **Authentication:** Password-based (see below for password retrieval) + +### Retrieving the Code Server Password + +After the first build, the code-server password is stored in: + +``` +configs/code-server/.config/code-server/config.yaml +``` + +Look for the `password:` field in that file. For example: + +```yaml +password: 0c0dca951a2d12eff1665817 +``` + +> **Note:** It is recommended **not** to change this password manually, as it is securely generated. + +## Main Configuration Options + +- `bind-addr`: The address and port code-server listens on (default: `127.0.0.1:8080`) +- `auth`: Authentication method (default: `password`) +- `password`: The login password (see above) +- `cert`: Whether to use HTTPS (default: `false`) + +## Installed Tools and Features + +The code-server environment includes: + +- **Node.js 18+** and **npm** +- **Claude Code** (`@anthropic-ai/claude-code`) globally installed +- **Python 3** and tools: + - `python3-pip`, `python3-venv`, `python3-full`, `pipx` +- **Image and PDF processing libraries**: + - `CairoSVG`, `Pillow`, `libcairo2-dev`, `libfreetype6-dev`, `libjpeg-dev`, `libpng-dev`, `libwebp-dev`, `libtiff5-dev`, `libopenjp2-7-dev`, `liblcms2-dev` + - `weasyprint`, `fonts-roboto` +- **Git** for version control and plugin management +- **Build tools**: `build-essential`, `pkg-config`, `python3-dev`, `zlib1g-dev` +- **MkDocs Material** and a wide range of MkDocs plugins, installed in a dedicated Python virtual environment at `/home/coder/.venv/mkdocs` +- **Convenience script**: `run-mkdocs` for running MkDocs commands easily + +### Using MkDocs + +The virtual environment for MkDocs is automatically added to your `PATH`. You can run MkDocs commands directly, or use the provided script. For example, to build the site, from a clean terminal we would rung: + +```bash +cd mkdocs +mkdocs build +``` + +## Claude Code Integration + +
+ +The code-server environment comes with **Claude Code** (`@anthropic-ai/claude-code`) globally installed via npm. + +### What is Claude Code? + +Claude Code is an AI-powered coding assistant by Anthropic, designed to help you write, refactor, and understand code directly within your development environment. + +### Usage + +- Access Claude Code features through the command palette or sidebar in code-server. +- Use Claude Code to generate code, explain code snippets, or assist with documentation and refactoring tasks. +- For more information, refer to the [Claude Code documentation](https://docs.anthropic.com/claude/docs/claude-code). + +> **Note:** Claude Code requires an API key or account with Anthropic for full functionality. Refer to the extension settings for configuration. + +### Call Claude + +To use claude simply type claude into the terminal and follow instructions. + +```bash +claude +``` + +## Shell Environment + +The `.bashrc` is configured to include the MkDocs virtual environment and user-local binaries in your `PATH` for convenience. + +## Code Navigation and Editing Features + +The code-server environment provides robust code navigation and editing features, including: + +- **IntelliSense**: Smart code completions based on variable types, function definitions, and imported modules. +- **Code Navigation**: Easily navigate to definitions, references, and symbol searches within your codebase. +- **Debugging Support**: Integrated debugging support for Node.js and Python, with breakpoints, call stacks, and interactive consoles. +- **Terminal Access**: Built-in terminal access to run commands, scripts, and version control operations. + +## Collaboration Features + +Code-server includes features to support collaboration: + +- **Live Share**: Collaborate in real-time with others, sharing your code and terminal sessions. +- **ChatGPT Integration**: AI-powered code assistance and chat-based collaboration. + +## Security Considerations + +When using code-server, consider the following security aspects: + +- **Password Management**: The default password is securely generated. Do not share it or expose it in public repositories. +- **Network Security**: Ensure that your firewall settings allow access to the code-server port (default: 8080) only from trusted networks. +- **Data Privacy**: Be cautious when uploading sensitive data or code to the server. Use environment variables or secure vaults for sensitive information. + +For more detailed information on configuring and using code-server, refer to the official [code-server documentation](https://coder.com/docs/). + diff --git a/mkdocs/docs/config/mkdocs.md b/mkdocs/docs/config/mkdocs.md new file mode 100644 index 0000000..dbda3f4 --- /dev/null +++ b/mkdocs/docs/config/mkdocs.md @@ -0,0 +1,143 @@ +# MkDocs Customization & Features Overview + +BNKops has been building our own features, widgets, and css styles for MKdocs material theme. + +This document explains the custom styling, repository widgets, and key features enabled in this MkDocs site. + +For more info on how to build your site see [Site Build](../build/site.md) + +--- + +## Using the Repository Widget in Documentation + +You can embed repository widgets directly in your Markdown documentation to display live repository stats and metadata. +To do this, add a `div` with the appropriate class and `data-repo` attribute for the repository you want to display. + +**Example (for a Gitea repository):** +```html +
+``` + +This will render a styled card with information about the `admin/changemaker.lite` repository: + +
+ +**Options:** +You can control the widget display with additional data attributes: +- `data-show-description="false"` — Hide the description +- `data-show-language="false"` — Hide the language +- `data-show-last-update="false"` — Hide the last update date + +**Example with options:** +```html +
+``` + +For GitHub repositories, use the `github-widget` class: +```html +
+``` + +--- + +## Custom CSS Styling (`stylesheets/extra.css`) + +The `extra.css` file provides extensive custom styling for the site, including: + +- **Login and Git Code Buttons**: + Custom styles for `.login-button` and `.git-code-button` to create visually distinct, modern buttons with hover effects. + +- **Code Block Improvements**: + Forces code blocks to wrap text (`white-space: pre-wrap`) and ensures inline code and tables with code display correctly on all devices. + +- **GitHub Widget Styles**: + Styles for `.github-widget` and its subcomponents, including: + - Card-like container with gradient backgrounds and subtle box-shadows. + - Header with icon, repo link, and stats (stars, forks, issues). + - Description area with accent border. + - Footer with language, last update, and license info. + - Loading and error states with spinners and error messages. + - Responsive grid layout for multiple widgets. + - Compact variant for smaller displays. + - Dark mode adjustments. + +- **Gitea Widget Styles**: + Similar to GitHub widget, but with Gitea branding (green accents). + Includes `.gitea-widget`, `.gitea-widget-container`, and related classes for header, stats, description, footer, loading, and error states. + +- **Responsive Design**: + Media queries ensure widgets and tables look good on mobile devices. + +--- + +## Repository Widgets + +### Data Generation (`hooks/repo_widget_hook.py`) + +- **Purpose**: + During the MkDocs build, this hook fetches metadata for a list of GitHub and Gitea repositories and writes JSON files to `docs/assets/repo-data/`. +- **How it works**: + - Runs before build (unless in `serve` mode). + - Fetches repo data (stars, forks, issues, language, etc.) via GitHub/Gitea APIs. + - Outputs a JSON file per repo (e.g., `lyqht-mini-qr.json`). + - Used by frontend widgets for fast, client-side rendering. + +### GitHub Widget (`javascripts/github-widget.js`) + +- **Purpose**: + Renders a card for each GitHub repository using the pre-generated JSON data. +- **Features**: + - Displays repo name, link, stars, forks, open issues, language, last update, and license. + - Shows loading spinner while fetching data. + - Handles errors gracefully. + - Supports dynamic content (re-initializes on DOM changes). + - Language color coding for popular languages. + +### Gitea Widget (`javascripts/gitea-widget.js`) + +- **Purpose**: + Renders a card for each Gitea repository using the pre-generated JSON data. +- **Features**: + - Similar to GitHub widget, but styled for Gitea. + - Shows repo name, link, stars, forks, open issues, language, last update. + - Loading and error states. + - Language color coding. + +--- + +## MkDocs Features (`mkdocs.yml`) + +Key features and plugins enabled: + +- **Material Theme**: + Modern, responsive UI with dark/light mode toggle, custom fonts, and accent colors. + +- **Navigation Enhancements**: + - Tabs, sticky navigation, instant loading, breadcrumbs, and sectioned navigation. + - Table of contents with permalinks. + +- **Content Features**: + - Code annotation, copy buttons, tooltips, and improved code highlighting. + - Admonitions, tabbed content, task lists, and emoji support. + +- **Plugins**: + - **Search**: Advanced search with custom tokenization. + - **Social**: OpenGraph/social card generation. + - **Blog**: Blogging support with archives and categories. + - **Tags**: Tagging for content organization. + +- **Custom Hooks**: + - `repo_widget_hook.py` for repository widget data. + +- **Extra CSS/JS**: + - Custom styles and scripts for widgets and homepage. + +- **Extra Configuration**: + - Social links, copyright. + +--- + +## Summary + +This MkDocs site is highly customized for developer documentation, with visually rich repository widgets, improved code and table rendering, and a modern, responsive UI. +All repository stats are fetched at build time for performance and reliability. diff --git a/mkdocs/docs/hooks/__pycache__/repo_widget_hook.cpython-311.pyc b/mkdocs/docs/hooks/__pycache__/repo_widget_hook.cpython-311.pyc index 2e2be22..bb804c7 100644 Binary files a/mkdocs/docs/hooks/__pycache__/repo_widget_hook.cpython-311.pyc and b/mkdocs/docs/hooks/__pycache__/repo_widget_hook.cpython-311.pyc differ diff --git a/mkdocs/docs/hooks/repo_widget_hook.py b/mkdocs/docs/hooks/repo_widget_hook.py index 1d79357..32faaba 100644 --- a/mkdocs/docs/hooks/repo_widget_hook.py +++ b/mkdocs/docs/hooks/repo_widget_hook.py @@ -6,6 +6,7 @@ Fetches repository data and generates JSON files during build import json import os import requests +import sys from pathlib import Path from typing import Dict, Any import logging @@ -19,6 +20,11 @@ def on_pre_build(config: Dict[str, Any]) -> None: Hook that runs before MkDocs builds the site Generates repository JSON data files """ + # Skip during serve mode to prevent infinite loops + if _is_serve_mode(): + logger.info("Serve mode detected, skipping repository widget data generation") + return + logger.info("Generating repository widget data...") # Define repositories to fetch - all repos from services.md @@ -60,6 +66,10 @@ def on_pre_build(config: Dict[str, Any]) -> None: { "repo": "gethomepage/homepage", "github": True + }, + { + "repo": "anthropics/claude-code", + "github": True } ] @@ -137,4 +147,9 @@ def generate_repo_data(repo_config: Dict[str, Any], output_dir: Path) -> None: def on_post_build(config: Dict[str, Any]) -> None: """Hook that runs after MkDocs builds the site""" - logger.info("Repository widget data generation complete") \ No newline at end of file + logger.info("Repository widget data generation complete") + +def _is_serve_mode() -> bool: + """Check if MkDocs is running in serve mode""" + # Check command line arguments + return 'serve' in sys.argv \ No newline at end of file diff --git a/mkdocs/docs/javascripts/home.js b/mkdocs/docs/javascripts/home.js index 1707903..e755e12 100644 --- a/mkdocs/docs/javascripts/home.js +++ b/mkdocs/docs/javascripts/home.js @@ -68,8 +68,8 @@ document.addEventListener('DOMContentLoaded', function() { }); }, observerOptions); - // Observe all grid cards - document.querySelectorAll('.grid-card').forEach((card, index) => { + // Observe all grid cards (exclude site-card and stat-card which have their own observer) + document.querySelectorAll('.grid-card:not(.site-card):not(.stat-card)').forEach((card, index) => { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; card.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; @@ -109,7 +109,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); - // Animated counter for stats + // Animated counter for hero stats (the smaller stat grid) const animateValue = (element, start, end, duration) => { const range = end - start; const increment = range / (duration / 16); @@ -125,8 +125,8 @@ document.addEventListener('DOMContentLoaded', function() { }, 16); }; - // Animate stat numbers on scroll - const statObserver = new IntersectionObserver((entries) => { + // Animate hero stat numbers on scroll (only for .stat-item, not .stat-card) + const heroStatObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const statNumber = entry.target.querySelector('.stat-number'); @@ -138,13 +138,129 @@ document.addEventListener('DOMContentLoaded', function() { animateValue(statNumber, 0, value, 1000); } } - statObserver.unobserve(entry.target); + heroStatObserver.unobserve(entry.target); } }); }, observerOptions); document.querySelectorAll('.stat-item').forEach(stat => { - statObserver.observe(stat); + heroStatObserver.observe(stat); + }); + + // Animated counter for proof stats - improved version + const proofStatObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const statCard = entry.target; + const counter = statCard.querySelector('.stat-counter'); + const statValue = statCard.getAttribute('data-stat'); + + if (counter && statValue && !counter.hasAttribute('data-animated')) { + counter.setAttribute('data-animated', 'true'); + + // Add counting class for visual effect + counter.classList.add('counting'); + + // Special handling for different stat types + if (statValue === '1') { + // AI Ready - just animate the text + counter.style.opacity = '0'; + counter.style.transform = 'scale(0.5)'; + setTimeout(() => { + counter.style.transition = 'all 0.8s ease'; + counter.style.opacity = '1'; + counter.style.transform = 'scale(1)'; + }, 200); + } else if (statValue === '30' || statValue === '2') { + // Time values like "30min", "2hr" + const originalText = counter.textContent; + counter.textContent = '0'; + counter.style.opacity = '0'; + setTimeout(() => { + counter.style.transition = 'all 0.8s ease'; + counter.style.opacity = '1'; + counter.textContent = originalText; + }, 200); + } else { + // Numeric values - animate the counting + const value = parseInt(statValue); + const originalText = counter.textContent; + counter.textContent = '0'; + + // Simple counting animation + let current = 0; + const increment = value / 30; // 30 steps + const timer = setInterval(() => { + current += increment; + if (current >= value) { + current = value; + clearInterval(timer); + // Restore original formatted text + setTimeout(() => { + counter.textContent = originalText; + }, 200); + } else { + counter.textContent = Math.floor(current).toLocaleString(); + } + }, 50); + } + } + proofStatObserver.unobserve(entry.target); + } + }); + }, { + threshold: 0.3, + rootMargin: '0px 0px -20px 0px' + }); + + // Observe proof stat cards (only those with data-stat attribute) + document.querySelectorAll('.stat-card[data-stat]').forEach(stat => { + proofStatObserver.observe(stat); + }); + + // Site card hover effects + document.querySelectorAll('.site-card').forEach(card => { + card.addEventListener('mouseenter', function() { + const icon = this.querySelector('.site-icon'); + if (icon) { + icon.style.animation = 'none'; + setTimeout(() => { + icon.style.animation = 'site-float 3s ease-in-out infinite'; + }, 10); + } + }); + }); + + // Staggered animation for proof cards - improved + const proofCardObserver = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const container = entry.target.closest('.sites-grid, .stats-grid'); + if (container) { + const allCards = Array.from(container.children); + const index = allCards.indexOf(entry.target); + + setTimeout(() => { + entry.target.style.opacity = '1'; + entry.target.style.transform = 'translateY(0)'; + }, index * 150); // Slightly longer delay for better effect + } + + proofCardObserver.unobserve(entry.target); + } + }); + }, { + threshold: 0.2, + rootMargin: '0px 0px -30px 0px' + }); + + // Observe site cards and stat cards for stagger animation + document.querySelectorAll('.site-card, .stat-card').forEach((card) => { + // Set initial state + card.style.opacity = '0'; + card.style.transform = 'translateY(30px)'; + card.style.transition = 'opacity 0.8s ease, transform 0.8s ease'; + proofCardObserver.observe(card); }); // Add parallax effect to hero section diff --git a/mkdocs/docs/overrides/home.html b/mkdocs/docs/overrides/home.html index a81bc0f..ea8d836 100644 --- a/mkdocs/docs/overrides/home.html +++ b/mkdocs/docs/overrides/home.html @@ -18,12 +18,13 @@
🤯 This Site Runs On Changemaker Lite

The Only Free and Open Source Political Campaign Platform

-

Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on ~$200 hardware and - with fewer corporate dependencies every day.

+

The medium is the message; if your competition is using the same platform, who is profiting? If your campaign is not self-hosted, who is control of your data? If you are not in control of your data, who has access to it?

+

Stop paying thousands of dollars a month to corporate platforms just to be surveilled. Your supporters data deserves better. Run your entire political campaign on your own hardware for free or work with BNKops to get a pre-configured server.

+

@@ -31,6 +32,7 @@

The Problem

+
💻 Website $100+/mo
💸 Canvassing: $100+/mo
📊 Nationbuilder: $500+/mo
📧 Mailchimp: $200+/mo
@@ -228,6 +230,87 @@
+ +
+
+
+

Real Sites, Real Results

+

Live sites powered by Changemaker Lite and integrated into our network

+
+ + + + + +
+

Live Performance Metrics

+
+
+
👀
+
100,000+
+
Website visits daily
+
Across BNKops managed sites
+
+
+
📧
+
500+
+
Emails sent daily
+
Newsletter & automation
+
+
+
🤖
+
24+
+
Tasks automated
+
Running continuously
+
+
+
+
30min
+
Setup time
+
From zero to production
+
+
+
⏱️
+
2hr
+
Configuration
+
Full customization
+
+
+
🧠
+
AI Ready
+
Local AI Integrations Available
+
Build With Plain Language
+
+
+
+
+
+
@@ -313,7 +396,7 @@
✓ Community support
✓ Learn the system
- Install Guide + Install Guide
diff --git a/mkdocs/docs/services/mkdocs.md b/mkdocs/docs/services/mkdocs.md index ed7b0ff..27a3956 100644 --- a/mkdocs/docs/services/mkdocs.md +++ b/mkdocs/docs/services/mkdocs.md @@ -1,8 +1,14 @@ # MkDocs Material + +
-Modern documentation site generator with live preview. +Modern documentation site generator with live preview. + +Looking for more info on BNKops code-server integration? + +[→ Code Server Configuration](../config/coder.md) ## Overview diff --git a/mkdocs/docs/stylesheets/home.css b/mkdocs/docs/stylesheets/home.css index 4a8576d..fbde54b 100644 --- a/mkdocs/docs/stylesheets/home.css +++ b/mkdocs/docs/stylesheets/home.css @@ -10,13 +10,13 @@ --trans-white: #FFFFFF; --trans-white-dim: #E0E0E0; - /* Dark theme colors */ + /* Dark theme colors - updated for consistent slate */ --home-dark-bg: #0a0a0a; - --home-dark-surface: #151515; - --home-dark-card: #1a1a1a; - --home-dark-border: #2a2a2a; - --home-dark-text: #e0e0e0; - --home-dark-text-muted: #999; + --home-dark-surface: #1e293b; /* slate-800 */ + --home-dark-card: #334155; /* slate-700 */ + --home-dark-border: #475569; /* slate-600 */ + --home-dark-text: #e2e8f0; /* slate-200 */ + --home-dark-text-muted: #94a3b8; /* slate-400 */ /* Grid colors */ --grid-primary: var(--trans-blue); @@ -104,13 +104,14 @@ body[data-md-template="home"] .md-main__inner { } .grid-card { - background: var(--md-default-bg-color); - border: 1px solid var(--grid-border); + background: var(--home-dark-card); + border: 1px solid var(--home-dark-border); border-radius: 4px; padding: var(--space-md); transition: all 0.2s ease; position: relative; overflow: hidden; + color: var(--home-dark-text); } .grid-card::before { @@ -307,20 +308,21 @@ body[data-md-template="home"] .md-main__inner { .section-header { text-align: center; margin-bottom: var(--space-lg); - padding: var(--space-sm) 0; - background: linear-gradient(to bottom, - rgba(10, 10, 10, 0.9) 0%, - rgba(10, 10, 10, 0.7) 70%, - transparent 100%); - backdrop-filter: blur(4px); - border-bottom: 1px solid var(--grid-border); + padding: var(--space-lg) var(--space-md); + background: #2d1b69; /* Deep purple solid background */ + border-radius: var(--home-radius); + border: 1px solid var(--mkdocs-purple); + box-shadow: 0 0 20px rgba(111, 66, 193, 0.3); + position: relative; + z-index: 10; /* Ensure it stays above other content */ + overflow: hidden; /* Prevent any content bleeding */ } .section-header h2 { font-size: 1.8rem; font-weight: 700; margin: 0 0 var(--space-xs) 0; - color: var(--home-dark-text); + color: var(--trans-white); position: relative; display: inline-block; } @@ -332,12 +334,12 @@ body[data-md-template="home"] .md-main__inner { left: 0; width: 100%; height: 2px; - background: linear-gradient(90deg, transparent, var(--trans-blue), transparent); + background: linear-gradient(90deg, transparent, var(--trans-pink), transparent); } .section-header p { font-size: 0.9rem; - color: var(--home-dark-text-muted); + color: var(--trans-white-dim); margin: 0; } @@ -345,11 +347,23 @@ body[data-md-template="home"] .md-main__inner { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--space-sm); + padding-top: var(--space-md); /* Add padding to accommodate service badges too */ } .service-card { + text-decoration: none; + color: inherit; text-align: center; + transition: all 0.3s ease; + position: relative; cursor: pointer; + min-height: 120px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: var(--space-md); /* Reset to normal padding */ + margin-top: 0; /* Remove margin, use grid padding instead */ } .service-card:hover .service-icon { @@ -402,6 +416,204 @@ body[data-md-template="home"] .md-main__inner { display: inline-block; } +/* ================================= + PROOFS SECTION - NEW + ================================= */ + +.proofs-grid { + padding: var(--space-lg) 0; + border-top: 1px solid var(--grid-border); +} + +/* Example Sites */ +.proof-sites { + margin-bottom: var(--space-xl); +} + +.proof-sites h3 { + font-size: 1.2rem; + margin: 0 0 var(--space-lg) 0; + color: var(--trans-blue); + text-align: center; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.sites-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-sm); + margin-bottom: var(--space-xl); + max-width: 900px; + margin-left: auto; + margin-right: auto; + padding-top: var(--space-md); /* Add padding to accommodate badges */ +} + +.site-card { + text-decoration: none; + color: inherit; + text-align: center; + transition: all 0.3s ease; + position: relative; + cursor: pointer; + min-height: 120px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: var(--space-md); + margin-top: 0; /* Remove margin, use grid padding instead */ +} + +.site-card:hover { + transform: translateY(-3px) scale(1.02); + box-shadow: 0 0 20px rgba(91, 206, 250, 0.4); +} + +.site-card.featured { + border-color: var(--trans-blue); + box-shadow: 0 0 15px rgba(91, 206, 250, 0.3); +} + +.site-badge { + position: absolute; + top: -4px; /* Bring badge even closer to card */ + left: 50%; + transform: translateX(-50%); + background: var(--trans-blue); + color: #000; + padding: 0.1rem 0.6rem; + border-radius: 10px; + font-size: 0.65rem; + font-weight: 700; + z-index: 5; + white-space: nowrap; /* Prevent text wrapping */ +} + +.site-icon { + font-size: 2.5rem; + margin-bottom: var(--space-sm); + animation: site-float 3s ease-in-out infinite; +} + +@keyframes site-float { + 0%, 100% { transform: translateY(0px); } + 50% { transform: translateY(-5px); } +} + +.site-name { + font-size: 1rem; + font-weight: 600; + margin-bottom: var(--space-xs); + color: var(--home-dark-text); +} + +.site-desc { + font-size: 0.8rem; + color: var(--home-dark-text-muted); +} + +/* Live Stats */ +.proof-stats h3 { + font-size: 1.2rem; + margin: 0 0 var(--space-lg) 0; + color: var(--trans-pink); + text-align: center; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.stats-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-sm); + max-width: 1000px; + margin: 0 auto; +} + +.stat-card { + text-align: center; + position: relative; + overflow: hidden; + min-height: 160px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: var(--space-md); +} + +.stat-card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, + var(--trans-blue), + var(--trans-pink), + var(--trans-blue)); + animation: stat-glow 2s ease-in-out infinite; +} + +@keyframes stat-glow { + 0%, 100% { opacity: 0.5; } + 50% { opacity: 1; } +} + +.stat-icon { + font-size: 2rem; + margin-bottom: var(--space-xs); + animation: stat-pulse 2s ease-in-out infinite; +} + +@keyframes stat-pulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.1); } +} + +.stat-counter { + font-size: 1.5rem; + font-weight: 700; + color: var(--trans-pink); /* Changed to pink to match section header */ + margin-bottom: var(--space-xs); + /* Removed text-shadow and animation for better readability */ +} + +.stat-label { + font-size: 0.9rem; + font-weight: 600; + color: var(--home-dark-text); + margin-bottom: var(--space-xs); +} + +.stat-detail { + font-size: 0.7rem; + color: var(--home-dark-text-muted); +} + +/* Animated counter effect */ +.stat-counter.counting { + animation: counter-count 1.2s ease-out; +} + +@keyframes counter-count { + 0% { + transform: scale(0.5) rotateY(-90deg); + opacity: 0; + } + 50% { + transform: scale(1.2) rotateY(0deg); + opacity: 0.8; + } + 100% { + transform: scale(1) rotateY(0deg); + opacity: 1; + } +} + /* ================================= COMPARISON TABLE - GRID STYLE ================================= */ @@ -474,11 +686,14 @@ body[data-md-template="home"] .md-main__inner { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: var(--space-sm); margin-bottom: var(--space-lg); + padding-top: var(--space-md); /* Add padding to accommodate badges */ } .option-card { text-align: center; position: relative; + padding-top: var(--space-md); /* Reduced padding since grid now has padding */ + margin-top: 0; /* Remove margin, use grid padding instead */ } .option-card.featured { @@ -499,7 +714,7 @@ body[data-md-template="home"] .md-main__inner { .option-badge { position: absolute; - top: -8px; + top: -4px; /* Bring badge even closer to card */ left: 50%; transform: translateX(-50%); background: var(--trans-blue); @@ -508,6 +723,8 @@ body[data-md-template="home"] .md-main__inner { border-radius: 10px; font-size: 0.65rem; font-weight: 700; + z-index: 5; + white-space: nowrap; /* Prevent text wrapping */ } .option-icon { @@ -582,7 +799,7 @@ body[data-md-template="home"] .md-main__inner { min-width: 100px; position: relative; overflow: hidden; - color: var(--mkdocs-purple-dark); + color: var(--trans-white) !important; /* Force white text with higher specificity */ } .btn::before { @@ -605,29 +822,52 @@ body[data-md-template="home"] .md-main__inner { .btn-primary { background: var(--mkdocs-purple); - color: var(--mkdocs-purple-dark); + color: var(--trans-white) !important; /* Force white text */ border-color: var(--mkdocs-purple); } .btn-primary:hover { background: var(--mkdocs-purple-dark); - color: #000; + color: var(--trans-white) !important; /* Force white text on hover */ box-shadow: 0 0 15px var(--mkdocs-purple); transform: translateY(-1px); } .btn-secondary { background: transparent; - color: var(--mkdocs-purple); + color: var(--trans-white) !important; /* Force white text */ border-color: var(--mkdocs-purple); } .btn-secondary:hover { background: var(--mkdocs-purple-dark); - color: #000; + color: var(--trans-white) !important; /* Force white text on hover */ box-shadow: 0 0 15px var(--mkdocs-purple); } +/* Ensure all button variations have white text */ +a.btn, +a.btn:visited, +a.btn:link, +a.btn:active { + color: var(--trans-white) !important; + text-decoration: none !important; +} + +a.btn-primary, +a.btn-primary:visited, +a.btn-primary:link, +a.btn-primary:active { + color: var(--trans-white) !important; +} + +a.btn-secondary, +a.btn-secondary:visited, +a.btn-secondary:link, +a.btn-secondary:active { + color: var(--trans-white) !important; +} + /* ================================= RESPONSIVE - ULTRA TIGHT ================================= */ @@ -651,6 +891,16 @@ body[data-md-template="home"] .md-main__inner { grid-template-columns: 1fr; } + .sites-grid { + grid-template-columns: repeat(2, 1fr); + max-width: 500px; + } + + .stats-grid { + grid-template-columns: repeat(2, 1fr); + max-width: 500px; + } + .comparison-header, .comparison-row { font-size: 0.7rem; @@ -679,6 +929,16 @@ body[data-md-template="home"] .md-main__inner { grid-template-columns: 1fr; } + .sites-grid { + grid-template-columns: 1fr; + max-width: 350px; + } + + .stats-grid { + grid-template-columns: 1fr; + max-width: 350px; + } + .service-card { padding: var(--space-sm); } @@ -686,6 +946,14 @@ body[data-md-template="home"] .md-main__inner { .hero-main h1 { font-size: 1.3rem; } + + .stat-counter { + font-size: 1.2rem; + } + + .site-icon { + font-size: 2rem; + } } /* Row cards at bottom: two cards in a row on desktop, stack on mobile */ @@ -734,4 +1002,72 @@ body[data-md-template="home"] .md-main__inner { letter-spacing: 0.03em; vertical-align: middle; box-shadow: 0 0 6px var(--mkdocs-purple-dark); +} + +/* Ensure all cards have consistent slate background */ +.grid-card, +.site-card, +.stat-card, +.service-card, +.option-card, +.final-cta, +.subscribe-card { + background: var(--home-dark-card) !important; + color: var(--home-dark-text) !important; +} + +/* Fix form elements in subscribe card */ +.subscribe-card input[type="email"], +.subscribe-card input[type="text"] { + background: var(--home-dark-surface); + color: var(--home-dark-text); + border: 1px solid var(--home-dark-border); + border-radius: 4px; + padding: 0.5rem; + width: 100%; + box-sizing: border-box; +} + +.subscribe-card input[type="email"]:focus, +.subscribe-card input[type="text"]:focus { + outline: none; + border-color: var(--trans-blue); + box-shadow: 0 0 0 2px rgba(91, 206, 250, 0.2); +} + +.subscribe-card label { + color: var(--home-dark-text-muted); + font-size: 0.9rem; +} + +.subscribe-card .action-btn { + background: var(--mkdocs-purple); + color: #000; + border: none; + padding: 0.5rem 1rem; + border-radius: 4px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; +} + +.subscribe-card .action-btn:hover { + background: var(--mkdocs-purple-dark); + transform: translateY(-1px); + box-shadow: 0 0 10px rgba(111, 66, 193, 0.4); +} + +/* Ensure all section content respects the header layering */ +.solution-grid, +.proofs-grid, +.comparison-grid, +.get-started-grid { + position: relative; + z-index: 1; /* Lower than section headers */ +} + +/* Make sure grid cards don't interfere with section headers */ +.grid-card { + position: relative; + z-index: 2; /* Higher than section content but lower than headers */ } \ No newline at end of file diff --git a/mkdocs/mkdocs.yml b/mkdocs/mkdocs.yml index b9e6167..3a952c2 100644 --- a/mkdocs/mkdocs.yml +++ b/mkdocs/mkdocs.yml @@ -149,13 +149,14 @@ nav: - phil/index.md - Who Reads Your Secrets: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/If%20you%20do%20politics%20who%20is%20reading%20your%20secrets%20-%20why%20you%20should%20de-corp%20your%20software%20stack/ - How To Not Get Got Making Content: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/How%20not%20to%20get%20got%20making%20content%20v2/ - - Digital Organizing: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/Distributed%20Digital%20Organizing%20is%20The%20Way%20Out/#why-not-give-it-a-shot + - Digital Organizing: https://docs.bnkops.com/archive/repo.archive/thatreallyblondehuman/Thoughts%20%F0%9F%A4%94/Distributed%20Digital%20Organizing%20is%20The%20Way%20Out/ - What is Security Culture: https://docs.bnkops.com/archive/repo.archive/Zines%20We%20Like%20%F0%9F%98%8E/What%20Is%20Security%20Culture%20%E2%98%A0/#what-is-security-culture - Cost Comparison: phil/cost-comparison.md - Getting Started: - build/index.md - - Build Server: build/build-server.md + - Build Server: build/server.md - Build Map: build/map.md + - Build Site: build/site.md - Services: - services/index.md - Homepage: services/homepage.md @@ -172,5 +173,11 @@ nav: - Configuration: - config/index.md - Cloudflare: config/cloudflare-config.md + - mkdocs: config/mkdocs.md + - Coder: config/coder.md + - Advanced Configuration: + - adv/index.md + - SSH + Tailscale + Ansible: adv/ansible.md + - SSH + VScode: adv/vscode-ssh.md - Blog: - blog/index.md diff --git a/mkdocs/site/404.html b/mkdocs/site/404.html index 880f8cb..3786233 100644 --- a/mkdocs/site/404.html +++ b/mkdocs/site/404.html @@ -473,6 +473,10 @@ Changemaker Archive. Learn more + + + + diff --git a/mkdocs/site/adv/ansible/index.html b/mkdocs/site/adv/ansible/index.html new file mode 100644 index 0000000..77a0314 --- /dev/null +++ b/mkdocs/site/adv/ansible/index.html @@ -0,0 +1,2831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SSH + Tailscale + Ansible - Changemaker Lite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+ + + + + +

Setting Up Ansible with Tailscale for Remote Server Management

+

Overview

+

This guide walks you through setting up Ansible to manage remote servers (like ThinkCentre units) using Tailscale for secure networking. This approach provides reliable remote access without complex port forwarding or VPN configurations.

+

In plainer language; this allows you to manage several Changemaker nodes remotely. If you are a full time campaigner, this can enable you to manage several campaigns infrastructure from a central location while each user gets their own Changemaker box.

+

What You'll Learn

+
    +
  • How to set up Ansible for infrastructure automation
  • +
  • How to configure secure remote access using Tailscale
  • +
  • How to troubleshoot common SSH and networking issues
  • +
  • Why this approach is better than alternatives like Cloudflare Tunnels for simple SSH access
  • +
+

Prerequisites

+
    +
  • Master Node: Your main computer running Ubuntu/Linux (control machine)
  • +
  • Target Nodes: Remote servers/ThinkCentres running Ubuntu/Linux
  • +
  • Both machines: Must have internet access
  • +
  • User Account: Same username on all machines (recommended)
  • +
+

Part 1: Initial Setup on Master Node

+

1. Create Ansible Directory Structure

+
# Create project directory
+mkdir ~/ansible_quickstart
+cd ~/ansible_quickstart
+
+# Create directory structure
+mkdir -p group_vars host_vars roles playbooks
+
+

2. Install Ansible

+
sudo apt update
+sudo apt install ansible
+
+

3. Generate SSH Keys (if not already done)

+
# Generate SSH key pair
+ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
+
+# Display public key (save this for later)
+cat ~/.ssh/id_rsa.pub
+
+

Part 2: Target Node Setup (Physical Access Required Initially)

+

1. Enable SSH on Target Node

+

Access each target node physically (monitor + keyboard):

+
# Update system
+sudo apt update && sudo apt upgrade -y
+
+# Install and enable SSH
+sudo apt install openssh-server
+sudo systemctl enable ssh
+sudo systemctl start ssh
+
+# Check SSH status
+sudo systemctl status ssh
+
+

2. Configure SSH Key Authentication

+
# Create .ssh directory
+mkdir -p ~/.ssh
+chmod 700 ~/.ssh
+
+# Create authorized_keys file
+nano ~/.ssh/authorized_keys
+
+

Paste your public key from the master node, then:

+
# Set proper permissions
+chmod 600 ~/.ssh/authorized_keys
+
+

3. Configure SSH Security

+
# Edit SSH config
+sudo nano /etc/ssh/sshd_config
+
+

Ensure these lines are uncommented:

+
PubkeyAuthentication yes
+AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
+
+
# Restart SSH service
+sudo systemctl restart ssh
+
+

4. Configure Firewall

+
# Check firewall status
+sudo ufw status
+
+# Allow SSH through firewall
+sudo ufw allow ssh
+
+# Fix home directory permissions (required for SSH keys)
+chmod 755 ~/
+
+

Part 3: Test Local SSH Connection

+

Before proceeding with remote access, test SSH connectivity locally:

+
# From master node, test SSH to target
+ssh username@<target-local-ip>
+
+

Common Issues and Solutions:

+
    +
  • Connection hangs: Check firewall rules (sudo ufw allow ssh)
  • +
  • Permission denied: Verify SSH keys and file permissions
  • +
  • SSH config errors: Ensure PubkeyAuthentication yes is set
  • +
+

Part 4: Set Up Tailscale for Remote Access

+

Why Tailscale Over Alternatives

+

We initially tried Cloudflare Tunnels but encountered complexity with:

+
    +
  • DNS routing issues
  • +
  • Complex configuration for SSH
  • +
  • Same-network testing problems
  • +
  • Multiple configuration approaches with varying success
  • +
+

Tailscale is superior because:

+
    +
  • Zero configuration mesh networking
  • +
  • Works from any network
  • +
  • Persistent IP addresses
  • +
  • No port forwarding needed
  • +
  • Free for personal use
  • +
+

1. Install Tailscale on Master Node

+
# Install Tailscale
+curl -fsSL https://tailscale.com/install.sh | sh
+
+# Connect to Tailscale network
+sudo tailscale up
+
+

Follow the authentication URL to connect with your Google/Microsoft/GitHub account.

+

2. Install Tailscale on Target Nodes

+

On each target node:

+
# Install Tailscale
+curl -fsSL https://tailscale.com/install.sh | sh
+
+# Connect to Tailscale network
+sudo tailscale up
+
+

Authenticate each device through the provided URL.

+

3. Get Tailscale IP Addresses

+

On each machine:

+
# Get your Tailscale IP
+tailscale ip -4
+
+

Each device receives a persistent IP like 100.x.x.x.

+

Part 5: Configure Ansible

+

1. Create Inventory File

+
# Create inventory.ini
+cd ~/ansible_quickstart
+nano inventory.ini
+
+

Content:

+
[thinkcenter]
+tc-node1 ansible_host=100.x.x.x ansible_user=your-username
+tc-node2 ansible_host=100.x.x.x ansible_user=your-username
+
+[all:vars]
+ansible_ssh_private_key_file=~/.ssh/id_rsa
+ansible_host_key_checking=False
+
+

Replace:

+
    +
  • 100.x.x.x with actual Tailscale IPs
  • +
  • your-username with your actual username
  • +
+

2. Test Ansible Connectivity

+
# Test connection to all nodes
+ansible all -i inventory.ini -m ping
+
+

Expected output:

+
tc-node1 | SUCCESS => {
+    "changed": false,
+    "ping": "pong"
+}
+
+

Part 6: Create and Run Playbooks

+

1. Simple Information Gathering Playbook

+
mkdir -p playbooks
+nano playbooks/info-playbook.yml
+
+

Content:

+
---
+- name: Gather Node Information
+  hosts: all
+  tasks:
+    - name: Get system information
+      setup:
+
+    - name: Display basic system info
+      debug:
+        msg: |
+          Hostname: {{ ansible_hostname }}
+          Operating System: {{ ansible_distribution }} {{ ansible_distribution_version }}
+          Architecture: {{ ansible_architecture }}
+          Memory: {{ ansible_memtotal_mb }}MB
+          CPU Cores: {{ ansible_processor_vcpus }}
+
+    - name: Show disk usage
+      command: df -h /
+      register: disk_info
+
+    - name: Display disk usage
+      debug:
+        msg: "Root filesystem usage: {{ disk_info.stdout_lines[1] }}"
+
+    - name: Check uptime
+      command: uptime
+      register: uptime_info
+
+    - name: Display uptime
+      debug:
+        msg: "System uptime: {{ uptime_info.stdout }}"
+
+

2. Run the Playbook

+
ansible-playbook -i inventory.ini playbooks/info-playbook.yml
+
+

Part 7: Advanced Playbook Example

+

System Setup Playbook

+
nano playbooks/setup-node.yml
+
+

Content:

+
---
+- name: Setup ThinkCentre Node
+  hosts: all
+  become: yes
+  tasks:
+    - name: Update package cache
+      apt:
+        update_cache: yes
+
+    - name: Install essential packages
+      package:
+        name:
+          - htop
+          - vim
+          - curl
+          - git
+          - docker.io
+        state: present
+
+    - name: Add user to docker group
+      user:
+        name: "{{ ansible_user }}"
+        groups: docker
+        append: yes
+
+    - name: Create management directory
+      file:
+        path: /opt/management
+        state: directory
+        owner: "{{ ansible_user }}"
+        group: "{{ ansible_user }}"
+
+

Troubleshooting Guide

+

SSH Issues

+

Problem: SSH connection hangs

+
    +
  • Check firewall: sudo ufw status and sudo ufw allow ssh
  • +
  • Verify SSH service: sudo systemctl status ssh
  • +
  • Test local connectivity first
  • +
+

Problem: Permission denied (publickey)

+
    +
  • Check SSH key permissions: chmod 600 ~/.ssh/authorized_keys
  • +
  • Verify home directory permissions: chmod 755 ~/
  • +
  • Ensure SSH config allows key auth: PubkeyAuthentication yes
  • +
+

Problem: Bad owner or permissions on SSH config

+
chmod 600 ~/.ssh/config
+
+

Ansible Issues

+

Problem: Host key verification failed

+
    +
  • Add to inventory: ansible_host_key_checking=False
  • +
+

Problem: Ansible command not found

+
sudo apt install ansible
+
+

Problem: Connection timeouts

+
    +
  • Verify Tailscale connectivity: ping <tailscale-ip>
  • +
  • Check if both nodes are connected: tailscale status
  • +
+

Tailscale Issues

+

Problem: Can't connect to Tailscale IP

+
    +
  • Verify both devices are authenticated: tailscale status
  • +
  • Check Tailscale is running: sudo systemctl status tailscaled
  • +
  • Restart Tailscale: sudo tailscale up
  • +
+

Scaling to Multiple Nodes

+

Adding New Nodes

+
    +
  1. Install Tailscale on new node
  2. +
  3. Set up SSH access (repeat Part 2)
  4. +
  5. Add to inventory.ini:
  6. +
+
[thinkcenter]
+tc-node1 ansible_host=100.125.148.60 ansible_user=bunker-admin
+tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin
+tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin
+
+

Group Management

+
[webservers]
+tc-node1 ansible_host=100.x.x.x ansible_user=bunker-admin
+tc-node2 ansible_host=100.x.x.x ansible_user=bunker-admin
+
+[databases]
+tc-node3 ansible_host=100.x.x.x ansible_user=bunker-admin
+
+[all:vars]
+ansible_ssh_private_key_file=~/.ssh/id_rsa
+ansible_host_key_checking=False
+
+

Run playbooks on specific groups:

+
ansible-playbook -i inventory.ini -l webservers playbook.yml
+
+

Best Practices

+

Security

+
    +
  • Use SSH keys, not passwords
  • +
  • Keep Tailscale client updated
  • +
  • Regular security updates via Ansible
  • +
  • Use become: yes only when necessary
  • +
+

Organization

+
ansible_quickstart/
+├── inventory.ini
+├── group_vars/
+├── host_vars/
+├── roles/
+└── playbooks/
+    ├── info-playbook.yml
+    ├── setup-node.yml
+    └── maintenance.yml
+
+

Monitoring and Maintenance

+

Create regular maintenance playbooks:

+
- name: System maintenance
+  hosts: all
+  become: yes
+  tasks:
+    - name: Update all packages
+      apt:
+        upgrade: dist
+        update_cache: yes
+
+    - name: Clean package cache
+      apt:
+        autoclean: yes
+        autoremove: yes
+
+

Alternative Approaches We Considered

+

Cloudflare Tunnels

+
    +
  • Pros: Good for web services, handles NAT traversal
  • +
  • Cons: Complex SSH setup, DNS routing issues, same-network problems
  • +
  • Use case: Better for web applications than SSH access
  • +
+

Traditional VPN

+
    +
  • Pros: Full network access
  • +
  • Cons: Complex setup, port forwarding required, router configuration
  • +
  • Use case: When you control the network infrastructure
  • +
+

SSH Reverse Tunnels

+
    +
  • Pros: Simple concept
  • +
  • Cons: Requires VPS, single point of failure, manual setup
  • +
  • Use case: Temporary access or when other methods fail
  • +
+

Conclusion

+

This setup provides:

+
    +
  • Reliable remote access from anywhere
  • +
  • Secure mesh networking with Tailscale
  • +
  • Infrastructure automation with Ansible
  • +
  • Easy scaling to multiple nodes
  • +
  • No complex networking required
  • +
+

The combination of Ansible + Tailscale is ideal for managing distributed infrastructure without the complexity of traditional VPN setups or the limitations of cloud-specific solutions.

+

Quick Reference Commands

+
# Check Tailscale status
+tailscale status
+
+# Test Ansible connectivity
+ansible all -i inventory.ini -m ping
+
+# Run playbook on all hosts
+ansible-playbook -i inventory.ini playbook.yml
+
+# Run playbook on specific group
+ansible-playbook -i inventory.ini -l groupname playbook.yml
+
+# Run single command on all hosts
+ansible all -i inventory.ini -m command -a "uptime"
+
+# SSH to node via Tailscale
+ssh username@100.x.x.x
+
+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mkdocs/site/adv/index.html b/mkdocs/site/adv/index.html new file mode 100644 index 0000000..52b84a8 --- /dev/null +++ b/mkdocs/site/adv/index.html @@ -0,0 +1,1496 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Advanced Configurations - Changemaker Lite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+ + + + + +

Advanced Configurations

+

We are also publishing how BNKops does several advanced workflows. These include things like assembling hardware, how to manage a network, how to manage several changemakers simultaneously, and integrating AI.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mkdocs/site/adv/vscode-ssh/index.html b/mkdocs/site/adv/vscode-ssh/index.html new file mode 100644 index 0000000..128604b --- /dev/null +++ b/mkdocs/site/adv/vscode-ssh/index.html @@ -0,0 +1,3122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SSH + VScode - Changemaker Lite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ + + +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + +
+
+
+ + + + + +
+
+
+ + + +
+
+ + + + + +

Remote Development with VSCode over Tailscale

+

Overview

+

This guide shows you how to set up Visual Studio Code for remote development on your servers using the Tailscale network. This allows you to develop directly on your remote ThinkCentre units as if they were local machines, with full access to files, terminals, and debugging capabilities.

+

What You'll Learn

+
    +
  • How to configure VSCode for remote SSH connections
  • +
  • How to set up remote development environments
  • +
  • How to manage multiple remote servers efficiently
  • +
  • How to troubleshoot common remote development issues
  • +
  • Best practices for remote development workflows
  • +
+

Prerequisites

+
    +
  • Completed the Ansible + Tailscale setup from the previous guide
  • +
  • VSCode installed on your local machine (master node)
  • +
  • Working SSH access to remote servers via Tailscale
  • +
  • Tailscale running on both local and remote machines
  • +
+

Verify Prerequisites

+

Before starting, ensure your setup is working:

+
# Check Tailscale connectivity
+tailscale status
+
+# Test SSH access
+ssh bunker-admin@100.125.148.60
+
+# Check VSCode is installed
+code --version
+
+

Part 1: Install and Configure Remote-SSH Extension

+

1. Install the Remote Development Extensions

+

Option A: Install Remote Development Pack (Recommended) +1. Open VSCode +2. Press Ctrl+Shift+X (or Cmd+Shift+X on Mac) +3. Search for "Remote Development" +4. Install the Remote Development extension pack by Microsoft

+

This pack includes: +- Remote - SSH +- Remote - SSH: Editing Configuration Files +- Remote - Containers +- Remote - WSL (Windows only)

+

Option B: Install Individual Extension +1. Search for "Remote - SSH" +2. Install Remote - SSH by Microsoft

+

2. Verify Installation

+

After installation, you should see: +- Remote Explorer icon in the Activity Bar (left sidebar) +- "Remote-SSH" commands in Command Palette (Ctrl+Shift+P)

+

Part 2: Configure SSH Connections

+

1. Access SSH Configuration

+

Method A: Through VSCode +1. Press Ctrl+Shift+P to open Command Palette +2. Type "Remote-SSH: Open SSH Configuration File..." +3. Select your SSH config file (usually the first option)

+

Method B: Direct File Editing +

# Edit SSH config file directly
+nano ~/.ssh/config
+

+

2. Add Server Configurations

+

Add your servers to the SSH config file:

+
# Primary ThinkCentre Node
+Host tc-node1
+    HostName 100.125.148.60
+    User bunker-admin
+    IdentityFile ~/.ssh/id_rsa
+    ForwardAgent yes
+    ServerAliveInterval 60
+    ServerAliveCountMax 3
+
+# Additional nodes (add as needed)
+Host tc-node2
+    HostName 100.x.x.x
+    User bunker-admin
+    IdentityFile ~/.ssh/id_rsa
+    ForwardAgent yes
+    ServerAliveInterval 60
+    ServerAliveCountMax 3
+
+Host tc-node3
+    HostName 100.x.x.x
+    User bunker-admin
+    IdentityFile ~/.ssh/id_rsa
+    ForwardAgent yes
+    ServerAliveInterval 60
+    ServerAliveCountMax 3
+
+

Configuration Options Explained: +- Host: Friendly name for the connection +- HostName: Tailscale IP address +- User: Username on the remote server +- IdentityFile: Path to your SSH private key +- ForwardAgent: Enables SSH agent forwarding for Git operations +- ServerAliveInterval: Keeps connection alive (prevents timeouts) +- ServerAliveCountMax: Number of keepalive attempts

+

3. Set Proper SSH Key Permissions

+
# Ensure SSH config has correct permissions
+chmod 600 ~/.ssh/config
+
+# Verify SSH key permissions
+chmod 600 ~/.ssh/id_rsa
+chmod 644 ~/.ssh/id_rsa.pub
+
+

Part 3: Connect to Remote Servers

+

1. Connect via Command Palette

+
    +
  1. Press Ctrl+Shift+P
  2. +
  3. Type "Remote-SSH: Connect to Host..."
  4. +
  5. Select your server (e.g., tc-node1)
  6. +
  7. VSCode will open a new window connected to the remote server
  8. +
+

2. Connect via Remote Explorer

+
    +
  1. Click the Remote Explorer icon in Activity Bar
  2. +
  3. Expand SSH Targets
  4. +
  5. Click the connect icon next to your server name
  6. +
+

3. Connect via Quick Menu

+
    +
  1. Click the remote indicator in bottom-left corner (looks like ><)
  2. +
  3. Select "Connect to Host..."
  4. +
  5. Choose your server from the list
  6. +
+

4. First Connection Process

+

On first connection, VSCode will: +1. Verify the host key (click "Continue" if prompted) +2. Install VSCode Server on the remote machine (automatic) +3. Open a remote window with access to the remote file system

+

Expected Timeline: +- First connection: 1-3 minutes (installs VSCode Server) +- Subsequent connections: 10-30 seconds

+

Part 4: Remote Development Environment Setup

+

1. Open Remote Workspace

+

Once connected:

+
# In the VSCode terminal (now running on remote server)
+# Navigate to your project
+cd /home/bunker-admin/projects
+
+# Open current directory in VSCode
+code .
+
+# Or open a specific project
+code /opt/myproject
+
+

2. Install Extensions on Remote Server

+

Extensions need to be installed separately on the remote server:

+

Essential Development Extensions: +1. Python (Microsoft) - Python development +2. GitLens (GitKraken) - Enhanced Git capabilities +3. Docker (Microsoft) - Container development +4. Prettier - Code formatting +5. ESLint - JavaScript linting +6. Auto Rename Tag - HTML/XML tag editing

+

To Install: +1. Go to Extensions (Ctrl+Shift+X) +2. Find your desired extension +3. Click "Install in SSH: tc-node1" (not local install)

+

3. Configure Git on Remote Server

+
# In VSCode terminal (remote)
+git config --global user.name "Your Name"
+git config --global user.email "your.email@example.com"
+
+# Test Git connectivity
+git clone https://github.com/yourusername/yourrepo.git
+
+

Part 5: Remote Development Workflows

+

1. File Management

+

File Explorer: +- Shows remote server's file system +- Create, edit, delete files directly +- Drag and drop between local and remote (limited)

+

File Transfer: +

# Upload files to remote (from local terminal)
+scp localfile.txt bunker-admin@100.125.148.60:/home/bunker-admin/
+
+# Download files from remote
+scp bunker-admin@100.125.148.60:/remote/path/file.txt ./local/path/
+

+

2. Terminal Usage

+

Integrated Terminal: +- Press Ctrl+` to open terminal +- Runs directly on remote server +- Multiple terminals supported +- Full shell access (bash, zsh, etc.)

+

Common Remote Terminal Commands: +

# Check system resources
+htop
+df -h
+free -h
+
+# Install packages
+sudo apt update
+sudo apt install nodejs npm
+
+# Start services
+sudo systemctl start nginx
+sudo docker-compose up -d
+

+

3. Port Forwarding

+

Automatic Port Forwarding: +VSCode automatically detects and forwards common development ports.

+

Manual Port Forwarding: +1. Open Ports tab in terminal panel +2. Click "Forward a Port" +3. Enter port number (e.g., 3000, 8080, 5000) +4. Access via http://localhost:port on local machine

+

Example: Web Development +

# Start a web server on remote (port 3000)
+npm start
+
+# VSCode automatically suggests forwarding port 3000
+# Access at http://localhost:3000 on your local machine
+

+

4. Debugging Remote Applications

+

Python Debugging: +

// .vscode/launch.json on remote server
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Python: Current File",
+            "type": "python",
+            "request": "launch",
+            "program": "${file}",
+            "console": "integratedTerminal"
+        }
+    ]
+}
+

+

Node.js Debugging: +

// .vscode/launch.json
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Launch Program",
+            "type": "node",
+            "request": "launch",
+            "program": "${workspaceFolder}/app.js"
+        }
+    ]
+}
+

+

Part 6: Advanced Configuration

+

1. Workspace Settings

+

Create remote-specific settings:

+
// .vscode/settings.json (on remote server)
+{
+    "python.defaultInterpreterPath": "/usr/bin/python3",
+    "terminal.integrated.shell.linux": "/bin/bash",
+    "files.autoSave": "afterDelay",
+    "editor.formatOnSave": true,
+    "remote.SSH.remotePlatform": {
+        "tc-node1": "linux"
+    }
+}
+
+

2. Multi-Server Management

+

Switch Between Servers: +1. Click remote indicator (bottom-left) +2. Select "Connect to Host..." +3. Choose different server

+

Compare Files Across Servers: +1. Open file from server A +2. Connect to server B in new window +3. Open corresponding file +4. Use "Compare with..." command

+

3. Sync Configuration

+

Settings Sync: +1. Enable Settings Sync in VSCode +2. Settings, extensions, and keybindings sync to remote +3. Consistent experience across all servers

+

Part 7: Project-Specific Setups

+

1. Python Development

+
# On remote server
+# Create virtual environment
+python3 -m venv venv
+source venv/bin/activate
+
+# Install packages
+pip install flask django requests
+
+# VSCode automatically detects Python interpreter
+
+

VSCode Python Configuration: +

// .vscode/settings.json
+{
+    "python.defaultInterpreterPath": "./venv/bin/python",
+    "python.linting.enabled": true,
+    "python.linting.pylintEnabled": true
+}
+

+

2. Node.js Development

+
# On remote server
+# Install Node.js
+curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
+sudo apt-get install -y nodejs
+
+# Create project
+mkdir myapp && cd myapp
+npm init -y
+npm install express
+
+

3. Docker Development

+
# On remote server
+# Install Docker (if not already done via Ansible)
+sudo apt install docker.io docker-compose
+sudo usermod -aG docker $USER
+
+# Create Dockerfile
+cat > Dockerfile << EOF
+FROM node:18
+WORKDIR /app
+COPY package*.json ./
+RUN npm install
+COPY . .
+EXPOSE 3000
+CMD ["npm", "start"]
+EOF
+
+

VSCode Docker Integration: +- Install Docker extension on remote +- Right-click Dockerfile → "Build Image" +- Manage containers from VSCode interface

+

Part 8: Troubleshooting Guide

+

Common Connection Issues

+

Problem: "Could not establish connection to remote host"

+

Solutions: +

# Check Tailscale connectivity
+tailscale status
+ping 100.125.148.60
+
+# Test SSH manually
+ssh bunker-admin@100.125.148.60
+
+# Check SSH config syntax
+ssh -T tc-node1
+

+

Problem: "Permission denied (publickey)"

+

Solutions: +

# Check SSH key permissions
+chmod 600 ~/.ssh/id_rsa
+chmod 600 ~/.ssh/config
+
+# Verify SSH agent
+ssh-add ~/.ssh/id_rsa
+ssh-add -l
+
+# Test SSH connection verbosely
+ssh -v bunker-admin@100.125.148.60
+

+

Problem: "Host key verification failed"

+

Solutions: +

# Remove old host key
+ssh-keygen -R 100.125.148.60
+
+# Or disable host key checking (less secure)
+# Add to SSH config:
+# StrictHostKeyChecking no
+

+

VSCode-Specific Issues

+

Problem: Extensions not working on remote

+

Solutions: +1. Install extensions specifically for remote server +2. Check extension compatibility with remote development +3. Reload VSCode window: Ctrl+Shift+P → "Developer: Reload Window"

+

Problem: Slow performance

+

Solutions: +- Use .vscode/settings.json to exclude large directories: +

{
+    "files.watcherExclude": {
+        "**/node_modules/**": true,
+        "**/.git/objects/**": true,
+        "**/dist/**": true
+    }
+}
+

+

Problem: Terminal not starting

+

Solutions: +

# Check shell path in remote settings
+"terminal.integrated.shell.linux": "/bin/bash"
+
+# Or let VSCode auto-detect
+"terminal.integrated.defaultProfile.linux": "bash"
+

+

Network and Performance Issues

+

Problem: Connection timeouts

+

Solutions: +Add to SSH config: +

ServerAliveInterval 60
+ServerAliveCountMax 3
+TCPKeepAlive yes
+

+

Problem: File transfer slow

+

Solutions: +- Use .vscodeignore to exclude unnecessary files +- Compress large files before transfer +- Use rsync for large file operations: +

rsync -avz --progress localdir/ bunker-admin@100.125.148.60:remotedir/
+

+

Part 9: Best Practices

+

Security Best Practices

+
    +
  1. Use SSH keys, never passwords
  2. +
  3. Keep SSH agent secure
  4. +
  5. Regular security updates on remote servers
  6. +
  7. Use VSCode's secure connection verification
  8. +
+

Performance Optimization

+
    +
  1. +

    Exclude unnecessary files: +

    // .vscode/settings.json
    +{
    +    "files.watcherExclude": {
    +        "**/node_modules/**": true,
    +        "**/.git/**": true,
    +        "**/dist/**": true,
    +        "**/build/**": true
    +    },
    +    "search.exclude": {
    +        "**/node_modules": true,
    +        "**/bower_components": true,
    +        "**/*.code-search": true
    +    }
    +}
    +

    +
  2. +
  3. +

    Use remote workspace for large projects

    +
  4. +
  5. Close unnecessary windows and extensions
  6. +
  7. Use efficient development workflows
  8. +
+

Development Workflow

+
    +
  1. +

    Use version control effectively: +

    # Always work in Git repositories
    +git status
    +git add .
    +git commit -m "feature: add new functionality"
    +git push origin main
    +

    +
  2. +
  3. +

    Environment separation: +

    # Development
    +ssh tc-node1
    +cd /home/bunker-admin/dev-projects
    +
    +# Production
    +ssh tc-node2
    +cd /opt/production-apps
    +

    +
  4. +
  5. +

    Backup important work: +

    # Regular backups via Git
    +git push origin main
    +
    +# Or manual backup
    +scp -r bunker-admin@100.125.148.60:/important/project ./backup/
    +

    +
  6. +
+

Part 10: Team Collaboration

+

Shared Development Servers

+

SSH Config for Team: +

# Shared development server
+Host team-dev
+    HostName 100.x.x.x
+    User dev-user
+    IdentityFile ~/.ssh/team_dev_key
+    ForwardAgent yes
+
+# Personal development
+Host my-dev
+    HostName 100.125.148.60
+    User bunker-admin
+    IdentityFile ~/.ssh/id_rsa
+

+

Project Structure

+
/opt/projects/
+├── project-a/
+│   ├── dev/          # Development branch
+│   ├── staging/      # Staging environment
+│   └── docs/         # Documentation
+├── project-b/
+└── shared-tools/     # Common utilities
+
+

Access Management

+
# Create shared project directory
+sudo mkdir -p /opt/projects
+sudo chown -R :developers /opt/projects
+sudo chmod -R g+w /opt/projects
+
+# Add users to developers group
+sudo usermod -a -G developers bunker-admin
+
+

Quick Reference

+

Essential VSCode Remote Commands

+
# Command Palette shortcuts
+Ctrl+Shift+P  "Remote-SSH: Connect to Host..."
+Ctrl+Shift+P  "Remote-SSH: Open SSH Configuration File..."
+Ctrl+Shift+P  "Remote-SSH: Kill VS Code Server on Host..."
+
+# Terminal
+Ctrl+`  Open integrated terminal
+Ctrl+Shift+`  Create new terminal
+
+# File operations
+Ctrl+O  Open file
+Ctrl+S  Save file
+Ctrl+Shift+E  Focus file explorer
+
+

SSH Connection Quick Test

+
# Test connectivity
+ssh -T tc-node1
+
+# Connect with verbose output
+ssh -v bunker-admin@100.125.148.60
+
+# Check SSH config
+ssh -F ~/.ssh/config tc-node1
+
+

Port Forwarding Commands

+
# Manual port forwarding
+ssh -L 3000:localhost:3000 bunker-admin@100.125.148.60
+
+# Background tunnel
+ssh -f -N -L 8080:localhost:80 bunker-admin@100.125.148.60
+
+

Conclusion

+

This remote development setup provides:

+
    +
  • Full development environment on remote servers
  • +
  • Seamless file access and editing capabilities
  • +
  • Integrated debugging and terminal access
  • +
  • Port forwarding for web development
  • +
  • Extension ecosystem available remotely
  • +
  • Secure connections through Tailscale network
  • +
+

The combination of VSCode Remote Development with Tailscale networking creates a powerful, flexible development environment that works from anywhere while maintaining security and performance.

+

Whether you're developing Python applications, Node.js services, or managing Docker containers, this setup provides a professional remote development experience that rivals local development while leveraging the power and resources of your remote servers.

+ + + + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + + +
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mkdocs/site/assets/images/social/adv/ansible.png b/mkdocs/site/assets/images/social/adv/ansible.png new file mode 100644 index 0000000..6009e1f Binary files /dev/null and b/mkdocs/site/assets/images/social/adv/ansible.png differ diff --git a/mkdocs/site/assets/images/social/adv/index.png b/mkdocs/site/assets/images/social/adv/index.png new file mode 100644 index 0000000..ea626c4 Binary files /dev/null and b/mkdocs/site/assets/images/social/adv/index.png differ diff --git a/mkdocs/site/assets/images/social/adv/vscode-ssh.png b/mkdocs/site/assets/images/social/adv/vscode-ssh.png new file mode 100644 index 0000000..d3b1a8a Binary files /dev/null and b/mkdocs/site/assets/images/social/adv/vscode-ssh.png differ diff --git a/mkdocs/site/assets/images/social/build/build-server.png b/mkdocs/site/assets/images/social/build/server.png similarity index 100% rename from mkdocs/site/assets/images/social/build/build-server.png rename to mkdocs/site/assets/images/social/build/server.png diff --git a/mkdocs/site/assets/images/social/build/site.png b/mkdocs/site/assets/images/social/build/site.png new file mode 100644 index 0000000..cc6851b Binary files /dev/null and b/mkdocs/site/assets/images/social/build/site.png differ diff --git a/mkdocs/site/assets/images/social/config/coder.png b/mkdocs/site/assets/images/social/config/coder.png new file mode 100644 index 0000000..31c3c68 Binary files /dev/null and b/mkdocs/site/assets/images/social/config/coder.png differ diff --git a/mkdocs/site/assets/images/social/config/mkdocs.png b/mkdocs/site/assets/images/social/config/mkdocs.png new file mode 100644 index 0000000..4345aff Binary files /dev/null and b/mkdocs/site/assets/images/social/config/mkdocs.png differ diff --git a/mkdocs/site/assets/repo-data/admin-changemaker.lite.json b/mkdocs/site/assets/repo-data/admin-changemaker.lite.json index f409dbc..5333f7d 100644 --- a/mkdocs/site/assets/repo-data/admin-changemaker.lite.json +++ b/mkdocs/site/assets/repo-data/admin-changemaker.lite.json @@ -6,11 +6,11 @@ "language": "HTML", "stars_count": 0, "forks_count": 0, - "open_issues_count": 0, - "updated_at": "2025-06-30T21:38:32-06:00", + "open_issues_count": 1, + "updated_at": "2025-07-01T09:33:43-06:00", "created_at": "2025-05-28T14:54:59-06:00", "clone_url": "https://gitea.bnkops.com/admin/changemaker.lite.git", "ssh_url": "git@gitea.bnkops.com:admin/changemaker.lite.git", "default_branch": "main", - "last_build_update": "2025-06-30T21:38:32-06:00" + "last_build_update": "2025-07-01T09:33:43-06:00" } \ No newline at end of file diff --git a/mkdocs/site/assets/repo-data/anthropics-claude-code.json b/mkdocs/site/assets/repo-data/anthropics-claude-code.json new file mode 100644 index 0000000..518e62f --- /dev/null +++ b/mkdocs/site/assets/repo-data/anthropics-claude-code.json @@ -0,0 +1,16 @@ +{ + "full_name": "anthropics/claude-code", + "name": "claude-code", + "description": "Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.", + "html_url": "https://github.com/anthropics/claude-code", + "language": "Shell", + "stars_count": 16934, + "forks_count": 929, + "open_issues_count": 1495, + "updated_at": "2025-07-02T17:38:19Z", + "created_at": "2025-02-22T17:41:21Z", + "clone_url": "https://github.com/anthropics/claude-code.git", + "ssh_url": "git@github.com:anthropics/claude-code.git", + "default_branch": "main", + "last_build_update": "2025-07-02T16:32:38Z" +} \ No newline at end of file diff --git a/mkdocs/site/assets/repo-data/coder-code-server.json b/mkdocs/site/assets/repo-data/coder-code-server.json index 3e3c526..c0c12d7 100644 --- a/mkdocs/site/assets/repo-data/coder-code-server.json +++ b/mkdocs/site/assets/repo-data/coder-code-server.json @@ -4,10 +4,10 @@ "description": "VS Code in the browser", "html_url": "https://github.com/coder/code-server", "language": "TypeScript", - "stars_count": 72508, - "forks_count": 6062, - "open_issues_count": 142, - "updated_at": "2025-07-01T15:16:52Z", + "stars_count": 72530, + "forks_count": 6064, + "open_issues_count": 143, + "updated_at": "2025-07-02T17:11:14Z", "created_at": "2019-02-27T16:50:41Z", "clone_url": "https://github.com/coder/code-server.git", "ssh_url": "git@github.com:coder/code-server.git", diff --git a/mkdocs/site/assets/repo-data/gethomepage-homepage.json b/mkdocs/site/assets/repo-data/gethomepage-homepage.json index d01b936..735b307 100644 --- a/mkdocs/site/assets/repo-data/gethomepage-homepage.json +++ b/mkdocs/site/assets/repo-data/gethomepage-homepage.json @@ -4,13 +4,13 @@ "description": "A highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.", "html_url": "https://github.com/gethomepage/homepage", "language": "JavaScript", - "stars_count": 24583, - "forks_count": 1519, + "stars_count": 24608, + "forks_count": 1520, "open_issues_count": 1, - "updated_at": "2025-07-01T15:20:04Z", + "updated_at": "2025-07-02T17:20:41Z", "created_at": "2022-08-24T07:29:42Z", "clone_url": "https://github.com/gethomepage/homepage.git", "ssh_url": "git@github.com:gethomepage/homepage.git", "default_branch": "dev", - "last_build_update": "2025-07-01T12:14:06Z" + "last_build_update": "2025-07-02T12:13:57Z" } \ No newline at end of file diff --git a/mkdocs/site/assets/repo-data/go-gitea-gitea.json b/mkdocs/site/assets/repo-data/go-gitea-gitea.json index e96b370..915ed37 100644 --- a/mkdocs/site/assets/repo-data/go-gitea-gitea.json +++ b/mkdocs/site/assets/repo-data/go-gitea-gitea.json @@ -4,13 +4,13 @@ "description": "Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD", "html_url": "https://github.com/go-gitea/gitea", "language": "Go", - "stars_count": 49327, - "forks_count": 5887, - "open_issues_count": 2706, - "updated_at": "2025-07-01T14:28:19Z", + "stars_count": 49339, + "forks_count": 5891, + "open_issues_count": 2711, + "updated_at": "2025-07-02T16:36:32Z", "created_at": "2016-11-01T02:13:26Z", "clone_url": "https://github.com/go-gitea/gitea.git", "ssh_url": "git@github.com:go-gitea/gitea.git", "default_branch": "main", - "last_build_update": "2025-07-01T13:44:05Z" + "last_build_update": "2025-07-02T00:37:56Z" } \ No newline at end of file diff --git a/mkdocs/site/assets/repo-data/knadh-listmonk.json b/mkdocs/site/assets/repo-data/knadh-listmonk.json index 184a06c..1ca3439 100644 --- a/mkdocs/site/assets/repo-data/knadh-listmonk.json +++ b/mkdocs/site/assets/repo-data/knadh-listmonk.json @@ -4,10 +4,10 @@ "description": "High performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.", "html_url": "https://github.com/knadh/listmonk", "language": "Go", - "stars_count": 17242, - "forks_count": 1657, - "open_issues_count": 104, - "updated_at": "2025-07-01T14:26:50Z", + "stars_count": 17248, + "forks_count": 1658, + "open_issues_count": 105, + "updated_at": "2025-07-02T10:32:44Z", "created_at": "2019-06-26T05:08:39Z", "clone_url": "https://github.com/knadh/listmonk.git", "ssh_url": "git@github.com:knadh/listmonk.git", diff --git a/mkdocs/site/assets/repo-data/n8n-io-n8n.json b/mkdocs/site/assets/repo-data/n8n-io-n8n.json index 11ee4cb..3480f52 100644 --- a/mkdocs/site/assets/repo-data/n8n-io-n8n.json +++ b/mkdocs/site/assets/repo-data/n8n-io-n8n.json @@ -4,13 +4,13 @@ "description": "Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.", "html_url": "https://github.com/n8n-io/n8n", "language": "TypeScript", - "stars_count": 113903, - "forks_count": 33364, - "open_issues_count": 1058, - "updated_at": "2025-07-01T15:22:32Z", + "stars_count": 114294, + "forks_count": 33577, + "open_issues_count": 1070, + "updated_at": "2025-07-02T17:42:44Z", "created_at": "2019-06-22T09:24:21Z", "clone_url": "https://github.com/n8n-io/n8n.git", "ssh_url": "git@github.com:n8n-io/n8n.git", "default_branch": "master", - "last_build_update": "2025-07-01T15:23:16Z" + "last_build_update": "2025-07-02T17:17:32Z" } \ No newline at end of file diff --git a/mkdocs/site/assets/repo-data/nocodb-nocodb.json b/mkdocs/site/assets/repo-data/nocodb-nocodb.json index d270c13..08cbf57 100644 --- a/mkdocs/site/assets/repo-data/nocodb-nocodb.json +++ b/mkdocs/site/assets/repo-data/nocodb-nocodb.json @@ -4,13 +4,13 @@ "description": "\ud83d\udd25 \ud83d\udd25 \ud83d\udd25 Open Source Airtable Alternative", "html_url": "https://github.com/nocodb/nocodb", "language": "TypeScript", - "stars_count": 55480, - "forks_count": 3987, - "open_issues_count": 714, - "updated_at": "2025-07-01T14:03:05Z", + "stars_count": 55505, + "forks_count": 3994, + "open_issues_count": 718, + "updated_at": "2025-07-02T17:05:35Z", "created_at": "2017-10-29T18:51:48Z", "clone_url": "https://github.com/nocodb/nocodb.git", "ssh_url": "git@github.com:nocodb/nocodb.git", "default_branch": "develop", - "last_build_update": "2025-07-01T14:26:19Z" + "last_build_update": "2025-07-02T16:01:20Z" } \ No newline at end of file diff --git a/mkdocs/site/assets/repo-data/squidfunk-mkdocs-material.json b/mkdocs/site/assets/repo-data/squidfunk-mkdocs-material.json index de092a5..59332e8 100644 --- a/mkdocs/site/assets/repo-data/squidfunk-mkdocs-material.json +++ b/mkdocs/site/assets/repo-data/squidfunk-mkdocs-material.json @@ -4,13 +4,13 @@ "description": "Documentation that simply works", "html_url": "https://github.com/squidfunk/mkdocs-material", "language": "Python", - "stars_count": 23763, - "forks_count": 3786, - "open_issues_count": 4, - "updated_at": "2025-07-01T13:38:53Z", + "stars_count": 23785, + "forks_count": 3787, + "open_issues_count": 5, + "updated_at": "2025-07-02T17:21:29Z", "created_at": "2016-01-28T22:09:23Z", "clone_url": "https://github.com/squidfunk/mkdocs-material.git", "ssh_url": "git@github.com:squidfunk/mkdocs-material.git", "default_branch": "master", - "last_build_update": "2025-07-01T12:56:28Z" + "last_build_update": "2025-07-02T16:12:25Z" } \ No newline at end of file diff --git a/mkdocs/site/blog/index.html b/mkdocs/site/blog/index.html index 9f07124..2ff2fb1 100644 --- a/mkdocs/site/blog/index.html +++ b/mkdocs/site/blog/index.html @@ -15,7 +15,7 @@ - + @@ -505,6 +505,10 @@ Changemaker Archive. Learn more + + + + @@ -703,7 +707,7 @@ Changemaker Archive. Learn more