Skip to content

RndmCodeGuy20/dyno

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

77 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Dyno

Logo Version License Go Version Build

A self-hostable, open-source DuckDNS alternative

Lightweight dynamic DNS service that lets you manage your DNS records without manual overhead.

Features β€’ Quick Start β€’ Documentation β€’ API Reference β€’ Contributing


πŸ“– Overview

Dyno is a self-hosted dynamic DNS service that eliminates the manual overhead of managing DNS records. Bring your own domain and Cloudflare tokens, and let Dyno handle the rest. Perfect for home labs, development environments, and self-hosted infrastructure.

Why Dyno?

  • 🏠 Self-Hosted: Complete control over your DNS data
  • πŸ” Secure: Token-based authentication for all operations
  • πŸš€ Fast: Built with Go for optimal performance
  • πŸ”Œ API-First: Comprehensive RESTful API for CLI/script automation
  • πŸ“¦ Easy Setup: Docker support with minimal configuration
  • 🌐 Cloudflare Integration: Currently supports Cloudflare DNS (more providers coming soon)
  • πŸ’Ύ Persistent Storage: PostgreSQL database for reliability

πŸ“– Detailed Documentation: Visit docs.dyno.rndmcode.in for comprehensive guides, tutorials, and API documentation.


✨ Features

  • Dynamic DNS Updates: Automatically update your DNS records when your IP changes
  • Multi-User Support: User authentication and authorization system
  • RESTful API: Full-featured API for programmatic access
  • Domain Management: Create, read, update, and delete DNS records
  • IPv4 Support: Automatic IP detection and DNS record updates
  • CLI-Friendly: Simple GET endpoints for easy curl-based updates
  • Dashboard Ready: API designed for web dashboard integration
  • Docker Support: Easy deployment with Docker and Docker Compose
  • CI/CD Pipeline: Automated builds and deployments with GitHub Actions

πŸš€ Quick Start

Prerequisites

  • Go 1.24+ (for local development)
  • PostgreSQL 12+
  • Docker & Docker Compose (recommended)
  • Cloudflare Account with API token
  • Your own domain managed by Cloudflare

Installation

Option 1: Docker (Recommended)

  1. Pull the Docker image:

    docker pull ghcr.io/rndmcodeguy20/dyno:production
  2. Create a .env file:

    # Server Configuration
    ENV=production
    HOST=0.0.0.0
    PORT=5010
    
    # Database Configuration
    DB_HOST=postgres
    DB_PORT=5432
    DB_USER=dyno
    DB_PASSWORD=your_secure_password
    DB_NAME=dyno_db
    
    # Cloudflare Configuration
    PROVIDER_API_KEY=your_cloudflare_api_token
    PROVIDER_EMAIL=your_cloudflare_email
    DOMAIN=yourdomain.com
  3. Create a docker-compose.yml:

    version: '3.8'
    
    services:
      postgres:
        image: postgres:16-alpine
        environment:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: dyno_db
        volumes:
          - postgres_data:/var/lib/postgresql/data
          - ./db/migrations:/docker-entrypoint-initdb.d
        ports:
          - "5432:5432"
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U postgres"]
          interval: 10s
          timeout: 5s
          retries: 5
    
      dyno:
        image: ghcr.io/rndmcodeguy20/dyno:latest
        env_file:
          - .env
        ports:
          - "5010:5010"
        depends_on:
          postgres:
            condition: service_healthy
        restart: unless-stopped
    
    volumes:
      postgres_data:
  4. Start the services:

    docker-compose up -d

Option 2: Build from Source

  1. Clone the repository:

    git clone https://github.com/rndmcodeguy20/dyno.git
    cd dyno
  2. Install dependencies:

    go mod download
  3. Set up PostgreSQL:

    # Run the migration scripts in db/migrations/
    psql -U postgres -f db/migrations/001_seed.sql
    psql -U postgres -d dyno_db -f db/migrations/002_unique_constraints_domain.sql
    psql -U postgres -d dyno_db -f db/migrations/003_add_dns_record_ids.sql
    psql -U postgres -d dyno_db -f db/migrations/004_add_token_hash_users.sql
  4. Configure environment variables:

    cp .env.example .env
    # Edit .env with your configuration
  5. Build and run:

    go build -o dyno ./cmd/server/main.go
    ./dyno

πŸ”§ Configuration

Environment Variables

Variable Description Required Default
ENV Environment (development/staging/production) Yes -
HOST Server host address No 0.0.0.0
PORT Server port No 5010
DB_HOST PostgreSQL host Yes -
DB_PORT PostgreSQL port No 5432
DB_USER Database username Yes -
DB_PASSWORD Database password Yes -
DB_NAME Database name Yes -
PROVIDER_API_KEY Cloudflare API token Yes -
PROVIDER_EMAIL Cloudflare account email Yes -
DOMAIN Your domain name Yes -

Getting a Cloudflare API Token

  1. Log in to your Cloudflare Dashboard
  2. Go to My Profile β†’ API Tokens
  3. Click Create Token
  4. Use the Edit zone DNS template
  5. Configure permissions:
    • Zone β†’ DNS β†’ Edit
    • Zone Resources β†’ Include β†’ Specific zone β†’ your domain
  6. Copy the generated token to PROVIDER_API_KEY

πŸ“š API Reference

Base URL

http://localhost:5010/api/v1

Authentication

All protected endpoints require a token in the Authorization header:

Authorization: Bearer <your_token>

Endpoints

Authentication

Sign Up
POST /api/v1/auth/signup
Content-Type: application/json

{
  "username": "johndoe",
  "email": "john@example.com",
  "password": "securepassword"
}
Login
POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "johndoe",
  "password": "securepassword"
}

Response:

{
  "success": true,
  "data": {
    "token": "your_auth_token",
    "user": {
      "id": 1,
      "username": "johndoe",
      "email": "john@example.com"
    }
  }
}

Domain Management

List Domains
GET /api/v1/domains
Authorization: Bearer <token>
Create Domain
POST /api/v1/domain
Authorization: Bearer <token>
Content-Type: application/json

{
  "domain_name": "home.yourdomain.com",
  "current_ip_v4": "203.0.113.10"
}
Update Domain by Name (CLI-Friendly)
# Automatic IP detection
curl "http://localhost:5010/api/v1/domain/update?domain=home.yourdomain.com&token=your_token"

# Explicit IP
curl "http://localhost:5010/api/v1/domain/update?domain=home.yourdomain.com&ip=203.0.113.10&token=your_token"
Update Domain by ID (RESTful)
PUT /api/v1/domain/{domainId}
Authorization: Bearer <token>
Content-Type: application/json

{
  "current_ip_v4": "203.0.113.20"
}
Delete Domain
DELETE /api/v1/domain/{domainId}
Authorization: Bearer <token>

User Profile

Get User Profile
GET /api/v1/user/profile
Authorization: Bearer <token>

πŸ› οΈ Usage Examples

Automated IP Updates with Cron

Create a script to update your IP automatically:

#!/bin/bash
# update-ip.sh

TOKEN="your_auth_token"
DOMAIN="home.yourdomain.com"
DYNO_URL="http://localhost:5010"

curl -s "${DYNO_URL}/api/v1/domain/update?domain=${DOMAIN}&token=${TOKEN}"

Add to crontab to run every 5 minutes:

*/5 * * * * /path/to/update-ip.sh

Python Script

import requests

DYNO_URL = "http://localhost:5010/api/v1"
TOKEN = "your_auth_token"

headers = {"Authorization": f"Bearer {TOKEN}"}

# List domains
response = requests.get(f"{DYNO_URL}/domains", headers=headers)
print(response.json())

# Update domain
response = requests.get(
    f"{DYNO_URL}/domain/update",
    params={"domain": "home.yourdomain.com"},
    headers=headers
)
print(response.json())

PowerShell Script (Windows)

$token = "your_auth_token"
$domain = "home.yourdomain.com"
$dynoUrl = "http://localhost:5010"

$headers = @{
    "Authorization" = "Bearer $token"
}

Invoke-RestMethod -Uri "$dynoUrl/api/v1/domain/update?domain=$domain" -Headers $headers

πŸ—οΈ Architecture

Tech Stack

  • Language: Go 1.24
  • Web Framework: Chi Router
  • Database: PostgreSQL with sqlx
  • DNS Provider SDK: Cloudflare Go SDK v6
  • Logging: Uber Zap
  • Authentication: Token-based (bcrypt hashing)

Project Structure

dyno/
β”œβ”€β”€ cmd/
β”‚   └── server/          # Application entry point
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ config/          # Configuration management
β”‚   β”œβ”€β”€ database/        # Database connection
β”‚   β”œβ”€β”€ handler/         # HTTP handlers
β”‚   β”œβ”€β”€ middleware/      # Custom middleware
β”‚   β”œβ”€β”€ models/          # Data models
β”‚   β”œβ”€β”€ repository/      # Data access layer
β”‚   β”œβ”€β”€ router/          # Route definitions
β”‚   β”œβ”€β”€ server/          # HTTP server setup
β”‚   └── service/         # Business logic
β”œβ”€β”€ pkg/
β”‚   β”œβ”€β”€ errors/          # Error handling utilities
β”‚   └── utils/           # Common utilities
β”œβ”€β”€ db/
β”‚   └── migrations/      # Database migrations
β”œβ”€β”€ build/               # Compiled binaries
└── docker-compose.yml   # Docker setup

πŸ”’ Security

  • Password Hashing: Bcrypt with configurable cost
  • Token Authentication: Secure token-based auth system
  • Input Validation: Request validation on all endpoints
  • SQL Injection Protection: Parameterized queries with sqlx
  • Rate Limiting: Configurable via middleware
  • HTTPS Ready: Deploy behind reverse proxy (Nginx/Traefik)

Security Best Practices

  1. Use strong passwords for database and user accounts
  2. Keep API tokens secure - never commit them to version control
  3. Run behind a reverse proxy with HTTPS in production
  4. Regularly update dependencies and Docker images
  5. Limit database access to the application only
  6. Use firewall rules to restrict access to sensitive ports

🚒 Deployment

Production Deployment

Docker with Reverse Proxy

Nginx Configuration Example:

server {
    listen 80;
    server_name dns.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name dns.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://localhost:5010;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Environment-Specific Builds

The project supports multiple environments via GitHub Actions:

  • staging: Deployed on push to staging branch
  • production: Deployed on push to master branch

Docker images are tagged with:

  • Semantic version (e.g., 0.0.1)
  • Commit SHA (e.g., 0.0.1-abc1234)
  • Environment tag (staging or production)

πŸ§ͺ Development

Prerequisites

  • Go 1.24+
  • PostgreSQL 12+
  • Make (optional, for taskfile)

Setup Development Environment

  1. Clone and enter directory:

    git clone https://github.com/rndmcodeguy20/dyno.git
    cd dyno
  2. Install dependencies:

    go mod download
  3. Set up local database:

    # Start PostgreSQL (via Docker)
    docker run -d \
      --name dyno-postgres \
      -e POSTGRES_PASSWORD=postgres \
      -p 5432:5432 \
      postgres:16-alpine
    
    # Run migrations
    psql -h localhost -U postgres -f db/migrations/001_seed.sql
  4. Create .env file:

    cp .env.example .env
    # Edit with your local configuration
  5. Run the application:

    go run cmd/server/main.go

Building

# Build for current platform
go build -o dyno ./cmd/server/main.go

# Build for Linux
GOOS=linux GOARCH=amd64 go build -o dyno-linux ./cmd/server/main.go

# Build with version info
go build -ldflags="-X 'main.Version=0.0.1'" -o dyno ./cmd/server/main.go

Testing

# Run tests
go test ./...

# Run tests with coverage
go test -cover ./...

# Run tests with verbose output
go test -v ./...

πŸ—ΊοΈ Roadmap

Current Version (v0.0.1)

  • βœ… Cloudflare DNS integration
  • βœ… User authentication and authorization
  • βœ… Domain CRUD operations
  • βœ… Automatic IP detection
  • βœ… RESTful API
  • βœ… Docker support
  • βœ… CI/CD pipeline

Upcoming Features

  • Additional DNS Providers
    • Route53 (AWS)
    • Google Cloud DNS
    • DigitalOcean DNS
    • Namecheap
  • IPv6 Support
  • Web Dashboard
    • User-friendly interface
    • Real-time DNS status
    • Domain management UI
  • Advanced Features
    • Webhook notifications
    • Multi-domain support per user
    • DNS record history/audit log
    • API rate limiting per user
    • Email notifications
  • Monitoring
    • Prometheus metrics
    • Health check endpoints
    • Status page

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

Contribution Guidelines

  • Follow Go best practices and conventions
  • Write tests for new features
  • Update documentation as needed
  • Keep commits atomic and well-described
  • Ensure CI/CD pipeline passes

Code Style

This project follows standard Go conventions:

  • Use gofmt for formatting
  • Run go vet for static analysis
  • Follow Effective Go guidelines

πŸ› Bug Reports & Feature Requests

Please use GitHub Issues to report bugs or request features:

  • Bug Report: Describe the issue, steps to reproduce, and expected behavior
  • Feature Request: Describe the feature and its use case

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


πŸ‘¨β€πŸ’» Author

Shantanu Mane


πŸ™ Acknowledgments


πŸ“ž Support

If you find this project helpful, please consider:

  • ⭐ Starring the repository
  • πŸ› Reporting bugs
  • πŸ’‘ Suggesting new features
  • 🀝 Contributing code
  • πŸ“’ Sharing with others

For questions and support, please open an issue on GitHub.


Built with ❀️ by the community

Report Bug β€’ Request Feature

About

Lightweight. Self-hostable DDNS

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages