mirror of
https://github.com/freedbygrace/DynamoDNS.git
synced 2026-09-03 14:17:56 +00:00
Document project architecture, setup, usage, and API endpoints
Adds comprehensive documentation including architecture, API reference, deployment, development, and user guides with README.md. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9111ef36-26c8-4085-84ca-a35dc1fec1b5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7083d608-d6d3-4a6a-9a27-6286c5109627/910f6160-6716-488e-83e6-61256595c269.jpg
This commit is contained in:
@@ -0,0 +1,129 @@
|
|||||||
|
# DynamoDNS
|
||||||
|
|
||||||
|
A comprehensive web-based dynamic DNS management platform offering advanced infrastructure control, monitoring, and multi-provider integration with a focus on user experience and security.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Multi-Provider DNS Management**: Support for Cloudflare, AWS Route53, GoDaddy, and custom providers
|
||||||
|
- **Dynamic DNS Updates**: Automatic IP detection and DNS record updates
|
||||||
|
- **Role-Based Access Control**: Granular permissions with customizable roles
|
||||||
|
- **Customer Management**: Support for multiple organizations with isolated access
|
||||||
|
- **Historical Tracking**: Complete audit trail of DNS changes
|
||||||
|
- **Performance Metrics**: Visualize DNS performance and activity
|
||||||
|
- **API Integration**: RESTful API with token-based authentication
|
||||||
|
- **Webhook Notifications**: Real-time notifications for DNS events
|
||||||
|
- **Multi-Factor Authentication**: Enhanced security for user accounts
|
||||||
|
- **Customizable Dashboards**: Personalized monitoring views
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
- **Backend**:
|
||||||
|
- Express.js for API server
|
||||||
|
- PostgreSQL for robust data storage
|
||||||
|
- Drizzle ORM for database interactions
|
||||||
|
- Passport.js for multi-method authentication
|
||||||
|
- WebSockets for real-time updates
|
||||||
|
|
||||||
|
- **Frontend**:
|
||||||
|
- React for user interface
|
||||||
|
- TanStack Query for data fetching and caching
|
||||||
|
- Shadcn UI components for consistent design
|
||||||
|
- Tailwind CSS for styling
|
||||||
|
- Recharts for data visualization
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Node.js (v18 or later)
|
||||||
|
- PostgreSQL (v14 or later)
|
||||||
|
- Modern web browser
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
1. Clone the repository:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/dynamodns.git
|
||||||
|
cd dynamodns
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Install dependencies:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Configure environment variables by creating a `.env` file:
|
||||||
|
```
|
||||||
|
DATABASE_URL=postgresql://username:password@localhost:5432/dynamodns
|
||||||
|
PORT=5000
|
||||||
|
SESSION_SECRET=your_secure_secret
|
||||||
|
ENABLE_REGISTRATION=false
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run database migrations:
|
||||||
|
```bash
|
||||||
|
npm run db:push
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Start the application:
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Access the application at http://localhost:5000
|
||||||
|
|
||||||
|
### Default Admin Account
|
||||||
|
|
||||||
|
On first launch, a default admin account is created:
|
||||||
|
- Username: `admin`
|
||||||
|
- Password: `admin`
|
||||||
|
|
||||||
|
**Important**: Change the default password immediately after first login.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Comprehensive documentation is available in the `/docs` directory:
|
||||||
|
|
||||||
|
- [User Guide](docs/user-guide.md) - For end users managing DNS records
|
||||||
|
- [API Reference](docs/api-reference.md) - For developers integrating with the API
|
||||||
|
- [Deployment Guide](docs/deployment-guide.md) - For system administrators
|
||||||
|
- [Development Guide](docs/development-guide.md) - For contributors
|
||||||
|
- [Architecture](docs/architecture.md) - System design and architecture overview
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
DynamoDNS can be deployed in various environments:
|
||||||
|
|
||||||
|
- **Standalone Server**: Direct installation on Linux/Windows servers
|
||||||
|
- **Docker**: Container-based deployment with Docker Compose
|
||||||
|
- **Cloud Platforms**: Deploy to AWS, Azure, Google Cloud, or other providers
|
||||||
|
|
||||||
|
See the [Deployment Guide](docs/deployment-guide.md) for detailed instructions.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We welcome contributions from the community! Please see our [Development Guide](docs/development-guide.md) for information on getting started with development.
|
||||||
|
|
||||||
|
To contribute:
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
||||||
|
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
||||||
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
||||||
|
5. Open a Pull Request
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For support or questions, please [open an issue](https://github.com/yourusername/dynamodns/issues) on GitHub, or contact the maintainers directly.
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
- The open source community for the amazing tools that make this project possible
|
||||||
|
- Contributors who have helped improve and maintain this project
|
||||||
|
- Users who have provided feedback and feature suggestions
|
||||||
@@ -0,0 +1,586 @@
|
|||||||
|
# DynamoDNS API Reference
|
||||||
|
|
||||||
|
This document provides detailed information about the DynamoDNS REST API endpoints, request/response formats, and authentication mechanisms.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
The API supports two authentication methods:
|
||||||
|
|
||||||
|
### Session Authentication (Web UI)
|
||||||
|
|
||||||
|
Used for browser-based interactions. Authenticate via:
|
||||||
|
- POST `/api/login`
|
||||||
|
- GET `/api/user` (verify current session)
|
||||||
|
- POST `/api/logout`
|
||||||
|
|
||||||
|
### API Token Authentication
|
||||||
|
|
||||||
|
Required for programmatic access:
|
||||||
|
- Include the token in the `Authorization` header: `Authorization: Bearer YOUR_API_TOKEN`
|
||||||
|
- API tokens can be created and managed through the web interface or via API
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
#### `POST /api/login`
|
||||||
|
|
||||||
|
Authenticates a user and creates a session.
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "string",
|
||||||
|
"password": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"username": "string",
|
||||||
|
"email": "string",
|
||||||
|
"fullName": "string",
|
||||||
|
"role": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `POST /api/register`
|
||||||
|
|
||||||
|
Registers a new user (if enabled).
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "string",
|
||||||
|
"email": "string",
|
||||||
|
"password": "string",
|
||||||
|
"fullName": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"username": "string",
|
||||||
|
"email": "string",
|
||||||
|
"fullName": "string",
|
||||||
|
"role": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `POST /api/logout`
|
||||||
|
|
||||||
|
Ends the current user session.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
HTTP 200 OK
|
||||||
|
|
||||||
|
#### `GET /api/user`
|
||||||
|
|
||||||
|
Retrieves the current authenticated user's information.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"username": "string",
|
||||||
|
"email": "string",
|
||||||
|
"fullName": "string",
|
||||||
|
"role": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `GET /api/auth/config`
|
||||||
|
|
||||||
|
Retrieves the authentication configuration.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"localAuthEnabled": true,
|
||||||
|
"registrationEnabled": false,
|
||||||
|
"ldapEnabled": false,
|
||||||
|
"oidcEnabled": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customers
|
||||||
|
|
||||||
|
#### `GET /api/customers`
|
||||||
|
|
||||||
|
Returns all customers the authenticated user has access to.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"name": "string",
|
||||||
|
"description": "string",
|
||||||
|
"email": "string",
|
||||||
|
"phone": "string",
|
||||||
|
"address": "string",
|
||||||
|
"city": "string",
|
||||||
|
"state": "string",
|
||||||
|
"zipCode": "string",
|
||||||
|
"country": "string",
|
||||||
|
"website": "string",
|
||||||
|
"industry": "string",
|
||||||
|
"notes": "string",
|
||||||
|
"accountManager": "string",
|
||||||
|
"billingEmail": "string",
|
||||||
|
"billingAddress": "string",
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `GET /api/customers/:id`
|
||||||
|
|
||||||
|
Returns a specific customer by ID.
|
||||||
|
|
||||||
|
**Response:** Customer object
|
||||||
|
|
||||||
|
#### `POST /api/customers`
|
||||||
|
|
||||||
|
Creates a new customer.
|
||||||
|
|
||||||
|
**Request:** Customer object without id and createdAt
|
||||||
|
**Response:** Created customer object
|
||||||
|
|
||||||
|
#### `PUT /api/customers/:id`
|
||||||
|
|
||||||
|
Updates an existing customer.
|
||||||
|
|
||||||
|
**Request:** Partial customer object
|
||||||
|
**Response:** Updated customer object
|
||||||
|
|
||||||
|
#### `DELETE /api/customers/:id`
|
||||||
|
|
||||||
|
Deletes a customer.
|
||||||
|
|
||||||
|
**Response:** HTTP 200 OK
|
||||||
|
|
||||||
|
### Domains
|
||||||
|
|
||||||
|
#### `GET /api/domains`
|
||||||
|
|
||||||
|
Returns all domains the user has access to.
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `customerId` (optional): Filter by customer ID
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"name": "string",
|
||||||
|
"customerId": "string",
|
||||||
|
"providerId": "string",
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "string",
|
||||||
|
"lastUpdated": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `GET /api/domains/:id`
|
||||||
|
|
||||||
|
Returns a specific domain by ID.
|
||||||
|
|
||||||
|
**Response:** Domain object
|
||||||
|
|
||||||
|
#### `POST /api/domains`
|
||||||
|
|
||||||
|
Creates a new domain.
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "string",
|
||||||
|
"customerId": "string",
|
||||||
|
"providerId": "string",
|
||||||
|
"isActive": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:** Created domain object
|
||||||
|
|
||||||
|
#### `PUT /api/domains/:id`
|
||||||
|
|
||||||
|
Updates an existing domain.
|
||||||
|
|
||||||
|
**Request:** Partial domain object
|
||||||
|
**Response:** Updated domain object
|
||||||
|
|
||||||
|
#### `DELETE /api/domains/:id`
|
||||||
|
|
||||||
|
Deletes a domain.
|
||||||
|
|
||||||
|
**Response:** HTTP 200 OK
|
||||||
|
|
||||||
|
### DNS Records
|
||||||
|
|
||||||
|
#### `GET /api/dns-records`
|
||||||
|
|
||||||
|
Returns DNS records the user has access to.
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `domainId` (optional): Filter by domain ID
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"name": "string",
|
||||||
|
"type": "A | AAAA | CNAME | MX | TXT | SRV | NS | CAA | PTR",
|
||||||
|
"content": "string",
|
||||||
|
"domainId": "string",
|
||||||
|
"priority": 0,
|
||||||
|
"ttl": 3600,
|
||||||
|
"proxied": false,
|
||||||
|
"isAutoIP": false,
|
||||||
|
"isActive": true,
|
||||||
|
"notes": "string",
|
||||||
|
"providerRecordId": "string",
|
||||||
|
"createdAt": "string",
|
||||||
|
"updatedAt": "string",
|
||||||
|
"currentIp": "string" // Only present when isAutoIP is true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `GET /api/dns-records/:id`
|
||||||
|
|
||||||
|
Returns a specific DNS record by ID.
|
||||||
|
|
||||||
|
**Response:** DNS record object
|
||||||
|
|
||||||
|
#### `POST /api/dns-records`
|
||||||
|
|
||||||
|
Creates a new DNS record.
|
||||||
|
|
||||||
|
**Request:** DNS record object without id, createdAt, updatedAt
|
||||||
|
**Response:** Created DNS record object
|
||||||
|
|
||||||
|
#### `PUT /api/dns-records/:id`
|
||||||
|
|
||||||
|
Updates an existing DNS record.
|
||||||
|
|
||||||
|
**Request:** Partial DNS record object
|
||||||
|
**Response:** Updated DNS record object
|
||||||
|
|
||||||
|
#### `DELETE /api/dns-records/:id`
|
||||||
|
|
||||||
|
Deletes a DNS record.
|
||||||
|
|
||||||
|
**Response:** HTTP 200 OK
|
||||||
|
|
||||||
|
#### `POST /api/dns-records/:id/toggle`
|
||||||
|
|
||||||
|
Toggles a DNS record's active status.
|
||||||
|
|
||||||
|
**Response:** Updated DNS record object
|
||||||
|
|
||||||
|
### Providers
|
||||||
|
|
||||||
|
#### `GET /api/providers`
|
||||||
|
|
||||||
|
Returns all DNS providers.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"name": "string",
|
||||||
|
"type": "cloudflare | route53 | godaddy | other",
|
||||||
|
"isActive": true,
|
||||||
|
"credentials": {
|
||||||
|
// Provider-specific credentials (redacted in response)
|
||||||
|
},
|
||||||
|
"createdAt": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `GET /api/providers/:id`
|
||||||
|
|
||||||
|
Returns a specific provider by ID.
|
||||||
|
|
||||||
|
**Response:** Provider object (credentials redacted)
|
||||||
|
|
||||||
|
#### `POST /api/providers`
|
||||||
|
|
||||||
|
Creates a new provider.
|
||||||
|
|
||||||
|
**Request:** Provider object with credentials
|
||||||
|
**Response:** Created provider object (credentials redacted)
|
||||||
|
|
||||||
|
#### `PUT /api/providers/:id`
|
||||||
|
|
||||||
|
Updates an existing provider.
|
||||||
|
|
||||||
|
**Request:** Partial provider object
|
||||||
|
**Response:** Updated provider object (credentials redacted)
|
||||||
|
|
||||||
|
#### `DELETE /api/providers/:id`
|
||||||
|
|
||||||
|
Deletes a provider.
|
||||||
|
|
||||||
|
**Response:** HTTP 200 OK
|
||||||
|
|
||||||
|
### DNS History
|
||||||
|
|
||||||
|
#### `GET /api/dns-history`
|
||||||
|
|
||||||
|
Returns DNS history records.
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `recordId` (optional): Filter by DNS record ID
|
||||||
|
- `domainId` (optional): Filter by domain ID
|
||||||
|
- `startDate` (optional): Filter by start date
|
||||||
|
- `endDate` (optional): Filter by end date
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"recordId": "string",
|
||||||
|
"domainId": "string",
|
||||||
|
"previousValue": "string",
|
||||||
|
"newValue": "string",
|
||||||
|
"changedBy": "string",
|
||||||
|
"createdAt": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Metrics
|
||||||
|
|
||||||
|
#### `GET /api/dns-metrics`
|
||||||
|
|
||||||
|
Returns DNS metrics.
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `recordId` (optional): Filter by DNS record ID
|
||||||
|
- `domainId` (optional): Filter by domain ID
|
||||||
|
- `type` (optional): Filter by metric type
|
||||||
|
- `startDate` (optional): Filter by start date
|
||||||
|
- `endDate` (optional): Filter by end date
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"recordId": "string",
|
||||||
|
"domainId": "string",
|
||||||
|
"type": "string",
|
||||||
|
"value": 0,
|
||||||
|
"timestamp": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Tokens
|
||||||
|
|
||||||
|
#### `GET /api/api-tokens`
|
||||||
|
|
||||||
|
Returns all API tokens for the authenticated user.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"name": "string",
|
||||||
|
"token": "string", // Only the first few and last few characters
|
||||||
|
"createdBy": "string",
|
||||||
|
"expiresAt": "string",
|
||||||
|
"isActive": true,
|
||||||
|
"role": "string",
|
||||||
|
"createdAt": "string",
|
||||||
|
"customerAccess": [
|
||||||
|
{
|
||||||
|
"customerId": "string",
|
||||||
|
"customerName": "string" // Populated for convenience
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `POST /api/api-tokens`
|
||||||
|
|
||||||
|
Creates a new API token.
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "string",
|
||||||
|
"expiresAt": "string", // optional
|
||||||
|
"role": "string",
|
||||||
|
"customerIds": ["string"] // optional, if empty, grants access to all customers
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:** Created API token object with the full token value (only returned once)
|
||||||
|
|
||||||
|
#### `PUT /api/api-tokens/:id`
|
||||||
|
|
||||||
|
Updates an existing API token.
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "string",
|
||||||
|
"expiresAt": "string",
|
||||||
|
"isActive": true,
|
||||||
|
"customerIds": ["string"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:** Updated API token object
|
||||||
|
|
||||||
|
#### `DELETE /api/api-tokens/:id`
|
||||||
|
|
||||||
|
Revokes an API token.
|
||||||
|
|
||||||
|
**Response:** HTTP 200 OK
|
||||||
|
|
||||||
|
### Webhooks
|
||||||
|
|
||||||
|
#### `GET /api/webhooks`
|
||||||
|
|
||||||
|
Returns all webhooks for the authenticated user's customers.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"customerId": "string",
|
||||||
|
"name": "string",
|
||||||
|
"url": "string",
|
||||||
|
"secret": "string", // Redacted
|
||||||
|
"events": ["string"],
|
||||||
|
"isActive": true,
|
||||||
|
"createdAt": "string",
|
||||||
|
"lastTriggered": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `POST /api/webhooks`
|
||||||
|
|
||||||
|
Creates a new webhook.
|
||||||
|
|
||||||
|
**Request:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"customerId": "string",
|
||||||
|
"name": "string",
|
||||||
|
"url": "string",
|
||||||
|
"secret": "string",
|
||||||
|
"events": ["string"],
|
||||||
|
"isActive": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:** Created webhook object (secret redacted)
|
||||||
|
|
||||||
|
#### `GET /api/webhook-logs`
|
||||||
|
|
||||||
|
Returns webhook delivery logs.
|
||||||
|
|
||||||
|
**Query Parameters:**
|
||||||
|
- `webhookId` (required): Filter by webhook ID
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "string",
|
||||||
|
"webhookId": "string",
|
||||||
|
"event": "string",
|
||||||
|
"payload": "object",
|
||||||
|
"response": "string",
|
||||||
|
"statusCode": 0,
|
||||||
|
"success": true,
|
||||||
|
"createdAt": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Utility Endpoints
|
||||||
|
|
||||||
|
#### `GET /api/public-ip`
|
||||||
|
|
||||||
|
Returns the public IP addresses of the client.
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ipv4": "string",
|
||||||
|
"ipv6": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Responses
|
||||||
|
|
||||||
|
All API endpoints return standard HTTP status codes:
|
||||||
|
|
||||||
|
- **400 Bad Request**: Invalid input
|
||||||
|
- **401 Unauthorized**: Missing or invalid authentication
|
||||||
|
- **403 Forbidden**: Insufficient permissions
|
||||||
|
- **404 Not Found**: Resource not found
|
||||||
|
- **500 Internal Server Error**: Server-side error
|
||||||
|
|
||||||
|
Error responses include a JSON body with error details:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"message": "Error description",
|
||||||
|
"code": "ERROR_CODE",
|
||||||
|
"details": {} // Additional error details when available
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rate Limiting
|
||||||
|
|
||||||
|
API requests are rate-limited to prevent abuse. Rate limit headers are included in all responses:
|
||||||
|
|
||||||
|
- `X-RateLimit-Limit`: Number of requests allowed in the current time window
|
||||||
|
- `X-RateLimit-Remaining`: Number of requests remaining in the current time window
|
||||||
|
- `X-RateLimit-Reset`: Time when the rate limit window resets (Unix timestamp)
|
||||||
|
|
||||||
|
When rate limits are exceeded, a 429 Too Many Requests response is returned.
|
||||||
|
|
||||||
|
## Pagination
|
||||||
|
|
||||||
|
List endpoints support pagination using the following query parameters:
|
||||||
|
|
||||||
|
- `page`: Page number (default: 1)
|
||||||
|
- `limit`: Items per page (default: 20, max: 100)
|
||||||
|
|
||||||
|
Paginated responses include metadata:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": [],
|
||||||
|
"pagination": {
|
||||||
|
"total": 0,
|
||||||
|
"pages": 0,
|
||||||
|
"page": 1,
|
||||||
|
"limit": 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# DynamoDNS Architecture
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
DynamoDNS is a comprehensive web-based dynamic DNS management platform that offers advanced infrastructure control, monitoring, and multi-provider integration. The application focuses on user experience and security while providing a robust solution for maintaining DNS records across multiple providers.
|
||||||
|
|
||||||
|
## System Architecture
|
||||||
|
|
||||||
|
The system is built on a modern web stack with the following components:
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- **Express.js Server**: Handles API requests, authentication, and business logic
|
||||||
|
- **PostgreSQL Database**: Provides robust data storage using the Neon serverless Postgres service
|
||||||
|
- **Drizzle ORM**: Manages database interactions and schema definition
|
||||||
|
- **Authentication System**: Supports multiple authentication methods (local, LDAP, OIDC)
|
||||||
|
- **DNS Provider Modules**: Integrates with various DNS providers (Cloudflare, AWS Route53, GoDaddy, etc.)
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- **React**: Powers the user interface
|
||||||
|
- **TanStack Query**: Manages data fetching and caching
|
||||||
|
- **Shadcn UI**: Provides consistent, accessible UI components
|
||||||
|
- **Tailwind CSS**: Handles styling with utility-first approach
|
||||||
|
- **Wouter**: Manages client-side routing
|
||||||
|
|
||||||
|
## Component Diagram
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Client Browser │
|
||||||
|
└───────────────────────────┬─────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌───────────────────────────▼─────────────────────────────────┐
|
||||||
|
│ Express Server │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ ┌──────────────┐ ┌────────────┐ │
|
||||||
|
│ │ Authentication │ │ API Routes │ │ WebSockets │ │
|
||||||
|
│ └─────────────────┘ └──────────────┘ └────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ ┌──────────────┐ ┌────────────┐ │
|
||||||
|
│ │ Storage Layer │ │ DNS Provider │ │ Metrics │ │
|
||||||
|
│ └────────┬────────┘ │ Modules │ │ Collection │ │
|
||||||
|
│ │ └──────┬───────┘ └────────────┘ │
|
||||||
|
└───────────┼──────────────────────────────────────────────────┘
|
||||||
|
│ │
|
||||||
|
┌───────────▼────────┐ ┌────────▼───────────────────────────┐
|
||||||
|
│ PostgreSQL DB │ │ External DNS APIs │
|
||||||
|
│ (via Drizzle ORM) │ │ (Cloudflare, Route53, GoDaddy) │
|
||||||
|
└────────────────────┘ └────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Schema
|
||||||
|
|
||||||
|
The database schema is defined using Drizzle ORM and includes the following main entities:
|
||||||
|
|
||||||
|
- **Users**: Application users with authentication details
|
||||||
|
- **Customers**: Organizations/accounts using the system
|
||||||
|
- **Customer User Assignments**: Many-to-many relationship connecting users to customers
|
||||||
|
- **Providers**: DNS service providers integrated with the system
|
||||||
|
- **Domains**: DNS domains managed by the system
|
||||||
|
- **DNS Records**: Individual DNS records within domains
|
||||||
|
- **DNS History**: Historical record of DNS changes
|
||||||
|
- **Metrics**: Performance and usage metrics
|
||||||
|
- **API Tokens**: Tokens for API authentication
|
||||||
|
- **Webhooks**: Notification integration points
|
||||||
|
|
||||||
|
## Authentication Flow
|
||||||
|
|
||||||
|
The application supports multiple authentication methods:
|
||||||
|
|
||||||
|
1. **Local Authentication**: Username/password stored in the database
|
||||||
|
2. **LDAP**: Integration with corporate directories
|
||||||
|
3. **OpenID Connect**: Single sign-on with identity providers
|
||||||
|
|
||||||
|
Authentication is managed via Passport.js with session-based authentication for the web interface and token-based authentication for API access.
|
||||||
|
|
||||||
|
## Authorization Model
|
||||||
|
|
||||||
|
The system implements a role-based access control (RBAC) model with the following roles:
|
||||||
|
|
||||||
|
- **Admin**: Full system access
|
||||||
|
- **Manager**: Can manage customers, domains, and DNS records
|
||||||
|
- **User**: Can manage assigned domains and DNS records
|
||||||
|
- **ReadOnly**: View-only access to assigned resources
|
||||||
|
- **Custom Roles**: User-defined roles with specific permissions
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
### DNS Record Updates
|
||||||
|
|
||||||
|
1. User initiates a DNS record update through the UI
|
||||||
|
2. Server validates the request and user permissions
|
||||||
|
3. Server dispatches the update to the appropriate DNS provider module
|
||||||
|
4. Provider module makes API calls to the external DNS service
|
||||||
|
5. Results are recorded in the database (success or failure)
|
||||||
|
6. Historical entry is created
|
||||||
|
7. Metrics are updated
|
||||||
|
8. Webhooks are triggered (if configured)
|
||||||
|
9. Client is notified of the outcome
|
||||||
|
|
||||||
|
### Automatic IP Updates
|
||||||
|
|
||||||
|
For dynamic DNS functionality:
|
||||||
|
|
||||||
|
1. Client periodically checks for IP changes
|
||||||
|
2. When a change is detected, updates are sent to the server
|
||||||
|
3. Server processes updates for all DNS records configured for automatic IP updates
|
||||||
|
4. External DNS providers are updated
|
||||||
|
5. History and metrics are recorded
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- **Authentication**: Multiple secure authentication methods
|
||||||
|
- **Authorization**: Granular role-based access control
|
||||||
|
- **API Tokens**: Scoped access with expiration
|
||||||
|
- **Audit Trail**: Comprehensive history logging
|
||||||
|
- **Credential Storage**: Secure storage of provider credentials
|
||||||
|
- **Input Validation**: Strict validation of all inputs
|
||||||
|
- **Rate Limiting**: Protection against abuse
|
||||||
@@ -0,0 +1,380 @@
|
|||||||
|
# DynamoDNS Deployment Guide
|
||||||
|
|
||||||
|
This guide outlines the steps required to deploy and configure DynamoDNS in your environment.
|
||||||
|
|
||||||
|
## System Requirements
|
||||||
|
|
||||||
|
### Minimum Requirements
|
||||||
|
|
||||||
|
- **Node.js**: v18.0.0 or higher
|
||||||
|
- **PostgreSQL**: v14.0 or higher (or Neon serverless database)
|
||||||
|
- **Operating System**: Any OS that supports Node.js (Linux recommended for production)
|
||||||
|
- **Memory**: 1GB RAM minimum (2GB+ recommended)
|
||||||
|
- **Storage**: 1GB for application, database size depends on usage
|
||||||
|
|
||||||
|
### Recommended Production Setup
|
||||||
|
|
||||||
|
- **Node.js**: Latest LTS version
|
||||||
|
- **PostgreSQL**: Latest stable version
|
||||||
|
- **Operating System**: Linux (Ubuntu 22.04 LTS or similar)
|
||||||
|
- **Memory**: 4GB RAM
|
||||||
|
- **Storage**: 10GB SSD
|
||||||
|
- **Web Server**: Nginx as a reverse proxy
|
||||||
|
- **SSL Certificate**: Let's Encrypt or similar
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Option 1: Docker Deployment (Recommended)
|
||||||
|
|
||||||
|
1. **Clone the repository**:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/dynamodns.git
|
||||||
|
cd dynamodns
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Configure environment variables**:
|
||||||
|
Create a `.env` file based on the `.env.example` template:
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env # Edit with your configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Build and start the containers**:
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Run database migrations**:
|
||||||
|
```bash
|
||||||
|
docker-compose exec app npm run db:push
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Create initial admin user** (if not using the automated setup):
|
||||||
|
```bash
|
||||||
|
docker-compose exec app npm run create-admin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: Manual Deployment
|
||||||
|
|
||||||
|
1. **Clone the repository**:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/dynamodns.git
|
||||||
|
cd dynamodns
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Install dependencies**:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Configure environment variables**:
|
||||||
|
Create a `.env` file with your configuration:
|
||||||
|
```
|
||||||
|
# Database configuration
|
||||||
|
DATABASE_URL=postgresql://user:password@localhost:5432/dynamodns
|
||||||
|
|
||||||
|
# Server configuration
|
||||||
|
PORT=5000
|
||||||
|
NODE_ENV=production
|
||||||
|
SESSION_SECRET=your_secure_session_secret
|
||||||
|
|
||||||
|
# Authentication configuration
|
||||||
|
ENABLE_REGISTRATION=false
|
||||||
|
|
||||||
|
# Optional: LDAP configuration
|
||||||
|
LDAP_ENABLED=false
|
||||||
|
LDAP_URL=ldap://ldap.example.com
|
||||||
|
LDAP_BIND_DN=cn=admin,dc=example,dc=com
|
||||||
|
LDAP_BIND_PASSWORD=password
|
||||||
|
LDAP_SEARCH_BASE=ou=users,dc=example,dc=com
|
||||||
|
LDAP_SEARCH_FILTER=(uid={{username}})
|
||||||
|
|
||||||
|
# Optional: OpenID Connect configuration
|
||||||
|
OIDC_ENABLED=false
|
||||||
|
OIDC_ISSUER=https://auth.example.com
|
||||||
|
OIDC_CLIENT_ID=your_client_id
|
||||||
|
OIDC_CLIENT_SECRET=your_client_secret
|
||||||
|
OIDC_CALLBACK_URL=https://dynamodns.example.com/api/auth/oidc/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Run database migrations**:
|
||||||
|
```bash
|
||||||
|
npm run db:push
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Build the application**:
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Start the application**:
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### Database Configuration
|
||||||
|
|
||||||
|
- **DATABASE_URL**: Connection string for PostgreSQL
|
||||||
|
|
||||||
|
### Server Configuration
|
||||||
|
|
||||||
|
- **PORT**: The port on which the server will listen (default: 5000)
|
||||||
|
- **NODE_ENV**: Environment (development/production)
|
||||||
|
- **HOST**: Host to bind to (default: 0.0.0.0)
|
||||||
|
- **SESSION_SECRET**: Secret for session encryption (generate a secure random string)
|
||||||
|
|
||||||
|
### Authentication Configuration
|
||||||
|
|
||||||
|
- **ENABLE_REGISTRATION**: Allow new user registration (true/false)
|
||||||
|
- **DEFAULT_ADMIN_USERNAME**: Username for the default admin (default: admin)
|
||||||
|
- **DEFAULT_ADMIN_PASSWORD**: Password for the default admin (set this for initial setup)
|
||||||
|
- **DEFAULT_ADMIN_EMAIL**: Email for the default admin (default: admin@example.com)
|
||||||
|
|
||||||
|
### LDAP Configuration (Optional)
|
||||||
|
|
||||||
|
- **LDAP_ENABLED**: Enable LDAP authentication (true/false)
|
||||||
|
- **LDAP_URL**: LDAP server URL
|
||||||
|
- **LDAP_BIND_DN**: DN for binding to LDAP
|
||||||
|
- **LDAP_BIND_PASSWORD**: Password for binding to LDAP
|
||||||
|
- **LDAP_SEARCH_BASE**: Base DN for user search
|
||||||
|
- **LDAP_SEARCH_FILTER**: Filter for finding users (use {{username}} as placeholder)
|
||||||
|
- **LDAP_USER_ATTR_USERNAME**: LDAP attribute for username (default: uid)
|
||||||
|
- **LDAP_USER_ATTR_EMAIL**: LDAP attribute for email (default: mail)
|
||||||
|
- **LDAP_USER_ATTR_DISPLAY_NAME**: LDAP attribute for display name (default: cn)
|
||||||
|
|
||||||
|
### OpenID Connect Configuration (Optional)
|
||||||
|
|
||||||
|
- **OIDC_ENABLED**: Enable OIDC authentication (true/false)
|
||||||
|
- **OIDC_ISSUER**: OIDC issuer URL
|
||||||
|
- **OIDC_CLIENT_ID**: Client ID for OIDC
|
||||||
|
- **OIDC_CLIENT_SECRET**: Client secret for OIDC
|
||||||
|
- **OIDC_CALLBACK_URL**: Callback URL for OIDC authentication
|
||||||
|
- **OIDC_SCOPE**: Scopes to request (default: "openid profile email")
|
||||||
|
|
||||||
|
## DNS Provider Configuration
|
||||||
|
|
||||||
|
DynamoDNS supports multiple DNS providers. Each requires specific configuration:
|
||||||
|
|
||||||
|
### Cloudflare
|
||||||
|
|
||||||
|
Required credentials:
|
||||||
|
- API Token or API Key + Email
|
||||||
|
- Zone IDs (optional, can be fetched automatically)
|
||||||
|
|
||||||
|
### AWS Route53
|
||||||
|
|
||||||
|
Required credentials:
|
||||||
|
- Access Key ID
|
||||||
|
- Secret Access Key
|
||||||
|
- Region
|
||||||
|
|
||||||
|
### GoDaddy
|
||||||
|
|
||||||
|
Required credentials:
|
||||||
|
- API Key
|
||||||
|
- API Secret
|
||||||
|
|
||||||
|
### Generic Provider
|
||||||
|
|
||||||
|
For custom or unsupported providers:
|
||||||
|
- API URL
|
||||||
|
- Authentication method
|
||||||
|
- Request format
|
||||||
|
|
||||||
|
## Setting Up Reverse Proxy
|
||||||
|
|
||||||
|
For production deployments, it's recommended to use a reverse proxy like Nginx or Apache.
|
||||||
|
|
||||||
|
### Nginx Configuration Example
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name dynamodns.example.com;
|
||||||
|
|
||||||
|
# Redirect to HTTPS
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name dynamodns.example.com;
|
||||||
|
|
||||||
|
ssl_certificate /path/to/cert.pem;
|
||||||
|
ssl_certificate_key /path/to/key.pem;
|
||||||
|
|
||||||
|
# SSL configuration
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
|
||||||
|
|
||||||
|
# Proxy to Node.js application
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:5000;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
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;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Backup and Maintenance
|
||||||
|
|
||||||
|
### Automated Backups
|
||||||
|
|
||||||
|
For PostgreSQL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add to crontab for daily backups
|
||||||
|
0 2 * * * pg_dump -U username -d dynamodns > /path/to/backup/dynamodns_$(date +\%Y\%m\%d).sql
|
||||||
|
```
|
||||||
|
|
||||||
|
For Neon PostgreSQL:
|
||||||
|
- Enable automated backups through the Neon dashboard
|
||||||
|
- Set an appropriate backup schedule and retention policy
|
||||||
|
|
||||||
|
### Database Maintenance
|
||||||
|
|
||||||
|
Regular maintenance tasks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vacuum the database to optimize performance
|
||||||
|
psql -U username -d dynamodns -c "VACUUM ANALYZE;"
|
||||||
|
|
||||||
|
# Check for slow queries
|
||||||
|
psql -U username -d dynamodns -c "SELECT * FROM pg_stat_activity WHERE state = 'active';"
|
||||||
|
```
|
||||||
|
|
||||||
|
## System Monitoring
|
||||||
|
|
||||||
|
### Health Check Endpoint
|
||||||
|
|
||||||
|
The application provides a health check endpoint at `/api/health` that returns:
|
||||||
|
- Application status
|
||||||
|
- Database connectivity
|
||||||
|
- DNS provider connectivity
|
||||||
|
|
||||||
|
### Recommended Monitoring Tools
|
||||||
|
|
||||||
|
- **Uptime Monitoring**: Pingdom, UptimeRobot, or similar
|
||||||
|
- **Application Monitoring**: New Relic, Datadog, or similar
|
||||||
|
- **Log Management**: ELK Stack, Graylog, or similar
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Securing Your Deployment
|
||||||
|
|
||||||
|
1. **Use HTTPS**: Always use SSL/TLS in production
|
||||||
|
2. **Firewall Configuration**: Restrict access to the server
|
||||||
|
3. **Regular Updates**: Keep all dependencies up to date
|
||||||
|
4. **Secure Credentials**: Use environment variables, not hardcoded values
|
||||||
|
5. **Rate Limiting**: Configure rate limiting to prevent abuse
|
||||||
|
|
||||||
|
### Data Protection
|
||||||
|
|
||||||
|
1. **Encryption**: Sensitive data is encrypted in the database
|
||||||
|
2. **Backups**: Regular encrypted backups
|
||||||
|
3. **Access Control**: Implement least privilege principle
|
||||||
|
4. **Audit Logs**: Monitor and review access logs
|
||||||
|
|
||||||
|
## Upgrading
|
||||||
|
|
||||||
|
### Standard Upgrade Process
|
||||||
|
|
||||||
|
1. **Backup your data**:
|
||||||
|
```bash
|
||||||
|
pg_dump -U username -d dynamodns > /path/to/backup/dynamodns_before_upgrade.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Pull the latest changes**:
|
||||||
|
```bash
|
||||||
|
git pull origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Install dependencies**:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Run database migrations**:
|
||||||
|
```bash
|
||||||
|
npm run db:push
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Rebuild the application**:
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Restart the service**:
|
||||||
|
```bash
|
||||||
|
# If using systemd
|
||||||
|
sudo systemctl restart dynamodns
|
||||||
|
|
||||||
|
# If using PM2
|
||||||
|
pm2 restart dynamodns
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Upgrade Process
|
||||||
|
|
||||||
|
1. **Pull the latest image**:
|
||||||
|
```bash
|
||||||
|
docker-compose pull
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Restart the containers**:
|
||||||
|
```bash
|
||||||
|
docker-compose down
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Run migrations**:
|
||||||
|
```bash
|
||||||
|
docker-compose exec app npm run db:push
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Database Connection Errors**:
|
||||||
|
- Check DATABASE_URL environment variable
|
||||||
|
- Verify network connectivity and firewall rules
|
||||||
|
- Ensure PostgreSQL is running
|
||||||
|
|
||||||
|
2. **Authentication Issues**:
|
||||||
|
- Verify SESSION_SECRET is set
|
||||||
|
- Check LDAP/OIDC configuration if using external authentication
|
||||||
|
|
||||||
|
3. **DNS Provider Integration Errors**:
|
||||||
|
- Verify API credentials for the DNS provider
|
||||||
|
- Check for rate limiting or IP restrictions
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
Access logs for troubleshooting:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Application logs
|
||||||
|
tail -f logs/app.log
|
||||||
|
|
||||||
|
# In Docker
|
||||||
|
docker-compose logs -f app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Getting Support
|
||||||
|
|
||||||
|
If you encounter issues not covered in this documentation:
|
||||||
|
|
||||||
|
1. Check the GitHub repository issues
|
||||||
|
2. Create a new issue with detailed information about your problem
|
||||||
|
3. Contact commercial support if you have a support agreement
|
||||||
@@ -0,0 +1,505 @@
|
|||||||
|
# DynamoDNS Development Guide
|
||||||
|
|
||||||
|
This guide provides information for developers who want to contribute to the DynamoDNS project or extend its functionality.
|
||||||
|
|
||||||
|
## Development Setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- **Node.js**: v18.0.0 or higher
|
||||||
|
- **npm**: v8.0.0 or higher
|
||||||
|
- **PostgreSQL**: v14.0 or higher (or Neon serverless database)
|
||||||
|
- **Git**: Latest version
|
||||||
|
|
||||||
|
### Getting Started
|
||||||
|
|
||||||
|
1. **Clone the repository**:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/dynamodns.git
|
||||||
|
cd dynamodns
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Install dependencies**:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Set up environment variables**:
|
||||||
|
Create a `.env` file based on the `.env.example` template:
|
||||||
|
```
|
||||||
|
# Database - Use a local PostgreSQL instance for development
|
||||||
|
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/dynamodns_dev
|
||||||
|
|
||||||
|
# Server
|
||||||
|
PORT=5000
|
||||||
|
NODE_ENV=development
|
||||||
|
SESSION_SECRET=dev_session_secret
|
||||||
|
|
||||||
|
# Auth - Enable registration for easier testing
|
||||||
|
ENABLE_REGISTRATION=true
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Set up the database**:
|
||||||
|
```bash
|
||||||
|
# Create the database
|
||||||
|
createdb dynamodns_dev
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
npm run db:push
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Start the development server**:
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Access the application**:
|
||||||
|
Open your browser and navigate to http://localhost:5000
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
dynamodns/
|
||||||
|
├── client/ # Frontend React application
|
||||||
|
│ ├── src/ # Source code
|
||||||
|
│ │ ├── components/ # Reusable UI components
|
||||||
|
│ │ ├── context/ # React context providers
|
||||||
|
│ │ ├── hooks/ # Custom React hooks
|
||||||
|
│ │ ├── lib/ # Utility functions
|
||||||
|
│ │ ├── pages/ # Page components
|
||||||
|
│ │ └── App.tsx # Main application component
|
||||||
|
├── docs/ # Documentation
|
||||||
|
├── migrations/ # Database migration files
|
||||||
|
├── server/ # Backend Express application
|
||||||
|
│ ├── providers/ # DNS provider integrations
|
||||||
|
│ ├── utils/ # Utility functions
|
||||||
|
│ ├── auth.ts # Authentication logic
|
||||||
|
│ ├── db.ts # Database connection
|
||||||
|
│ ├── index.ts # Application entry point
|
||||||
|
│ ├── routes.ts # API routes
|
||||||
|
│ ├── storage.ts # Storage interface
|
||||||
|
│ └── vite.ts # Vite integration
|
||||||
|
├── shared/ # Shared code between client and server
|
||||||
|
│ └── schema.ts # Database schema with Drizzle ORM
|
||||||
|
└── various config files # Configuration files for the project
|
||||||
|
```
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
- **Express.js**: Web server framework
|
||||||
|
- **Drizzle ORM**: Database ORM for TypeScript
|
||||||
|
- **PostgreSQL**: Relational database
|
||||||
|
- **Passport.js**: Authentication middleware
|
||||||
|
- **WebSockets**: Real-time communication
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
- **React**: UI library
|
||||||
|
- **TanStack Query**: Data fetching and caching
|
||||||
|
- **Shadcn UI**: Component library built on Radix UI
|
||||||
|
- **Tailwind CSS**: Utility-first CSS framework
|
||||||
|
- **Wouter**: Lightweight routing
|
||||||
|
- **Zod**: Schema validation
|
||||||
|
- **React Hook Form**: Form handling
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Frontend Architecture
|
||||||
|
|
||||||
|
The frontend follows a component-based architecture with React:
|
||||||
|
|
||||||
|
- **Context Providers**: Manage global state (auth, customer, theme)
|
||||||
|
- **Hooks**: Custom hooks for data fetching and business logic
|
||||||
|
- **Pages**: Top-level components for different routes
|
||||||
|
- **Components**: Reusable UI building blocks
|
||||||
|
|
||||||
|
Data flow utilizes TanStack Query for client-side data fetching and caching:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Example query
|
||||||
|
const { data, isLoading, error } = useQuery({
|
||||||
|
queryKey: ['/api/domains'],
|
||||||
|
enabled: !!user
|
||||||
|
});
|
||||||
|
|
||||||
|
// Example mutation
|
||||||
|
const mutation = useMutation({
|
||||||
|
mutationFn: async (data) => {
|
||||||
|
const res = await apiRequest('POST', '/api/domains', data);
|
||||||
|
return await res.json();
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['/api/domains'] });
|
||||||
|
// Handle success
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
// Handle error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backend Architecture
|
||||||
|
|
||||||
|
The backend follows a layered architecture:
|
||||||
|
|
||||||
|
1. **Routes Layer**: API endpoints and request handling
|
||||||
|
2. **Service Layer**: Business logic
|
||||||
|
3. **Data Access Layer**: Database interactions via Drizzle ORM
|
||||||
|
4. **Provider Layer**: Integrations with external DNS services
|
||||||
|
|
||||||
|
The application uses a storage interface pattern to abstract database operations:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Example storage interface method
|
||||||
|
async getUser(id: string): Promise<User | undefined> {
|
||||||
|
const [user] = await db.select().from(users).where(eq(users.id, id));
|
||||||
|
return user || undefined;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding Features
|
||||||
|
|
||||||
|
### Adding a New DNS Provider
|
||||||
|
|
||||||
|
1. **Create a provider module**:
|
||||||
|
Create a new file in `server/providers/` directory (e.g., `cloudflare.ts`).
|
||||||
|
|
||||||
|
2. **Implement the provider interface**:
|
||||||
|
```typescript
|
||||||
|
import { DNSProvider, DNSRecord, DNSProviderError } from './types';
|
||||||
|
|
||||||
|
export class CloudflareProvider implements DNSProvider {
|
||||||
|
constructor(private credentials: any) {
|
||||||
|
// Initialize with provider credentials
|
||||||
|
}
|
||||||
|
|
||||||
|
async createRecord(record: DNSRecord): Promise<string> {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateRecord(recordId: string, record: DNSRecord): Promise<void> {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteRecord(recordId: string): Promise<void> {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRecord(recordId: string): Promise<DNSRecord> {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Register the provider**:
|
||||||
|
Add the provider to the provider factory in `server/providers/index.ts`.
|
||||||
|
|
||||||
|
### Adding a New API Endpoint
|
||||||
|
|
||||||
|
1. **Create the route handler**:
|
||||||
|
Add your endpoint to `server/routes.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
app.get('/api/your-endpoint', (req, res) => {
|
||||||
|
// Implementation
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Add validation**:
|
||||||
|
Use Zod to validate request inputs:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const schema = z.object({
|
||||||
|
name: z.string().min(1),
|
||||||
|
// Other fields
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post('/api/your-endpoint', (req, res) => {
|
||||||
|
const result = schema.safeParse(req.body);
|
||||||
|
if (!result.success) {
|
||||||
|
return res.status(400).json({ errors: result.error.format() });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation with validated data
|
||||||
|
const data = result.data;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Use the storage interface**:
|
||||||
|
Interact with the database using the storage interface:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
app.get('/api/your-endpoint/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const item = await storage.getItem(req.params.id);
|
||||||
|
if (!item) {
|
||||||
|
return res.status(404).json({ message: 'Not found' });
|
||||||
|
}
|
||||||
|
res.json(item);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: 'Server error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding a New UI Component
|
||||||
|
|
||||||
|
1. **Create the component**:
|
||||||
|
Create a new file in the appropriate directory under `client/src/components/`.
|
||||||
|
|
||||||
|
2. **Implement the component**:
|
||||||
|
```tsx
|
||||||
|
import React from 'react';
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
|
||||||
|
interface MyComponentProps {
|
||||||
|
title: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyComponent({ title, children }: MyComponentProps) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>{title}</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{children}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Use the component**:
|
||||||
|
Import and use your component in a page or another component.
|
||||||
|
|
||||||
|
## Database Schema Management
|
||||||
|
|
||||||
|
The project uses Drizzle ORM with a schema defined in `shared/schema.ts`.
|
||||||
|
|
||||||
|
### Adding a New Table
|
||||||
|
|
||||||
|
1. **Define the table**:
|
||||||
|
```typescript
|
||||||
|
export const myNewTable = pgTable('my_new_table', {
|
||||||
|
id: text('id').primaryKey().defaultRandom(),
|
||||||
|
name: text('name').notNull(),
|
||||||
|
createdAt: timestamp('created_at').defaultNow().notNull(),
|
||||||
|
customerId: text('customer_id').references(() => customers.id, { onDelete: 'cascade' }),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Define relations**:
|
||||||
|
```typescript
|
||||||
|
export const myNewTableRelations = relations(myNewTable, ({ one }) => ({
|
||||||
|
customer: one(customers, {
|
||||||
|
fields: [myNewTable.customerId],
|
||||||
|
references: [customers.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Create insert schema and types**:
|
||||||
|
```typescript
|
||||||
|
export const insertMyNewTableSchema = createInsertSchema(myNewTable).pick({
|
||||||
|
name: true,
|
||||||
|
customerId: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type InsertMyNewTable = z.infer<typeof insertMyNewTableSchema>;
|
||||||
|
export type MyNewTable = typeof myNewTable.$inferSelect;
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Update the storage interface**:
|
||||||
|
Add methods to `server/storage.ts` for CRUD operations on your new table.
|
||||||
|
|
||||||
|
5. **Push the schema changes**:
|
||||||
|
```bash
|
||||||
|
npm run db:push
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
|
||||||
|
The project uses Jest for unit testing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all tests
|
||||||
|
npm test
|
||||||
|
|
||||||
|
# Run tests with coverage
|
||||||
|
npm test -- --coverage
|
||||||
|
|
||||||
|
# Run specific test file
|
||||||
|
npm test -- src/path/to/test.test.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Writing Tests
|
||||||
|
|
||||||
|
Example test for a utility function:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/utils/formatDate.test.ts
|
||||||
|
import { formatDate } from './formatDate';
|
||||||
|
|
||||||
|
describe('formatDate', () => {
|
||||||
|
it('formats a date correctly', () => {
|
||||||
|
const date = new Date('2023-01-01T12:00:00Z');
|
||||||
|
expect(formatDate(date)).toBe('Jan 1, 2023');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles null values', () => {
|
||||||
|
expect(formatDate(null)).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Example test for a React component using React Testing Library:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/components/Button.test.tsx
|
||||||
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
|
import { Button } from './Button';
|
||||||
|
|
||||||
|
describe('Button', () => {
|
||||||
|
it('renders correctly', () => {
|
||||||
|
render(<Button>Click me</Button>);
|
||||||
|
expect(screen.getByText('Click me')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls onClick when clicked', () => {
|
||||||
|
const handleClick = jest.fn();
|
||||||
|
render(<Button onClick={handleClick}>Click me</Button>);
|
||||||
|
fireEvent.click(screen.getByText('Click me'));
|
||||||
|
expect(handleClick).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Testing
|
||||||
|
|
||||||
|
For API endpoints, use Supertest:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/routes/domains.test.ts
|
||||||
|
import request from 'supertest';
|
||||||
|
import { app } from '../app';
|
||||||
|
import { db } from '../db';
|
||||||
|
|
||||||
|
describe('Domains API', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
// Set up test data
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
// Clean up test data
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /api/domains returns domains', async () => {
|
||||||
|
const response = await request(app)
|
||||||
|
.get('/api/domains')
|
||||||
|
.set('Authorization', `Bearer ${testToken}`);
|
||||||
|
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
expect(response.body).toHaveLength(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Style and Linting
|
||||||
|
|
||||||
|
The project uses ESLint and Prettier for code style and linting:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run ESLint
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# Fix ESLint issues
|
||||||
|
npm run lint:fix
|
||||||
|
|
||||||
|
# Format code with Prettier
|
||||||
|
npm run format
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commit Guidelines
|
||||||
|
|
||||||
|
We follow the Conventional Commits specification:
|
||||||
|
|
||||||
|
- `feat`: A new feature
|
||||||
|
- `fix`: A bug fix
|
||||||
|
- `docs`: Documentation changes
|
||||||
|
- `style`: Changes that do not affect the meaning of the code
|
||||||
|
- `refactor`: Code changes that neither fix a bug nor add a feature
|
||||||
|
- `perf`: Performance improvements
|
||||||
|
- `test`: Adding or fixing tests
|
||||||
|
- `chore`: Changes to the build process or auxiliary tools
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
feat(dns-records): add support for SRV records
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### Server-side Debugging
|
||||||
|
|
||||||
|
Add logging with debug statements:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import debug from 'debug';
|
||||||
|
|
||||||
|
const log = debug('dynamodns:server');
|
||||||
|
|
||||||
|
app.get('/api/domains', (req, res) => {
|
||||||
|
log('Fetching domains for user', req.user?.id);
|
||||||
|
// Implementation
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the application with debug enabled:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DEBUG=dynamodns:* npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client-side Debugging
|
||||||
|
|
||||||
|
Use React DevTools for component inspection and debugging.
|
||||||
|
|
||||||
|
For network debugging, use the browser's developer tools and the Network tab.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
See the [Deployment Guide](./deployment-guide.md) for information on deploying the application.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. **Fork the repository**
|
||||||
|
2. **Create a feature branch**:
|
||||||
|
```bash
|
||||||
|
git checkout -b feature/your-feature-name
|
||||||
|
```
|
||||||
|
3. **Make your changes**
|
||||||
|
4. **Run tests**:
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
5. **Commit your changes** following the commit guidelines
|
||||||
|
6. **Push to your fork**:
|
||||||
|
```bash
|
||||||
|
git push origin feature/your-feature-name
|
||||||
|
```
|
||||||
|
7. **Create a Pull Request**
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- **Drizzle ORM Documentation**: [https://orm.drizzle.team/docs/overview](https://orm.drizzle.team/docs/overview)
|
||||||
|
- **React Documentation**: [https://react.dev/](https://react.dev/)
|
||||||
|
- **TanStack Query Documentation**: [https://tanstack.com/query/latest](https://tanstack.com/query/latest)
|
||||||
|
- **Shadcn UI Documentation**: [https://ui.shadcn.com/](https://ui.shadcn.com/)
|
||||||
|
- **Tailwind CSS Documentation**: [https://tailwindcss.com/docs](https://tailwindcss.com/docs)
|
||||||
|
- **Express.js Documentation**: [https://expressjs.com/](https://expressjs.com/)
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
# DynamoDNS User Guide
|
||||||
|
|
||||||
|
This guide provides detailed instructions for using the DynamoDNS platform to manage your DNS records across multiple providers.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Account Setup
|
||||||
|
|
||||||
|
1. **Login**: Access the application using your provided credentials at the login page.
|
||||||
|
2. **First-time Setup**: If this is your first time, you'll be prompted to create a new customer account.
|
||||||
|
3. **Dashboard**: After login, you'll be directed to the main dashboard showing your DNS records and metrics.
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
|
||||||
|
The main navigation menu includes:
|
||||||
|
|
||||||
|
- **Dashboard**: Overview of your DNS infrastructure
|
||||||
|
- **Domains**: Manage domain registrations
|
||||||
|
- **DNS Records**: Create and manage DNS records
|
||||||
|
- **History**: View historical changes to DNS records
|
||||||
|
- **Metrics**: Analyze performance and usage statistics
|
||||||
|
- **Webhooks**: Configure notification endpoints
|
||||||
|
- **API Tokens**: Manage access tokens for API usage
|
||||||
|
- **Settings**: Configure user and customer settings
|
||||||
|
|
||||||
|
## Managing Customers
|
||||||
|
|
||||||
|
Customers represent organizations that own domains in the system. Each customer can have multiple domains and users.
|
||||||
|
|
||||||
|
### Creating a Customer
|
||||||
|
|
||||||
|
1. Navigate to Settings → Customer tab
|
||||||
|
2. Click "Create New Customer"
|
||||||
|
3. Fill in the required information:
|
||||||
|
- Customer Name (required)
|
||||||
|
- Description (optional)
|
||||||
|
- Contact Information (email, phone)
|
||||||
|
- Address Information
|
||||||
|
- Website and Industry
|
||||||
|
- Notes and Account Manager
|
||||||
|
4. Click "Create Customer"
|
||||||
|
|
||||||
|
### Editing Customer Details
|
||||||
|
|
||||||
|
1. Navigate to Settings → Customer tab
|
||||||
|
2. Update the information as needed
|
||||||
|
3. Click "Save Changes"
|
||||||
|
|
||||||
|
### Switching Between Customers
|
||||||
|
|
||||||
|
Use the customer selector in the top navigation bar to switch between different customers you have access to.
|
||||||
|
|
||||||
|
## Managing Domains
|
||||||
|
|
||||||
|
Domains are the DNS zones that contain your DNS records.
|
||||||
|
|
||||||
|
### Adding a Domain
|
||||||
|
|
||||||
|
1. Navigate to the Domains page
|
||||||
|
2. Click "Add Domain"
|
||||||
|
3. Enter the domain name (e.g., example.com)
|
||||||
|
4. Select the DNS provider (Cloudflare, Route53, GoDaddy, etc.)
|
||||||
|
5. Enter necessary provider credentials (if not already configured)
|
||||||
|
6. Click "Add Domain"
|
||||||
|
|
||||||
|
### Managing Domain Settings
|
||||||
|
|
||||||
|
1. Navigate to the Domains page
|
||||||
|
2. Click on a domain to view its details
|
||||||
|
3. Use the "Edit" button to modify domain settings
|
||||||
|
4. Use the "Delete" button to remove the domain
|
||||||
|
|
||||||
|
## Managing DNS Records
|
||||||
|
|
||||||
|
DNS records define how domain names are mapped to resources on the internet.
|
||||||
|
|
||||||
|
### Adding a DNS Record
|
||||||
|
|
||||||
|
1. Navigate to the DNS Records page
|
||||||
|
2. Filter by domain if needed
|
||||||
|
3. Click "Add Record"
|
||||||
|
4. Select the record type (A, AAAA, CNAME, MX, TXT, etc.)
|
||||||
|
5. Enter the required fields:
|
||||||
|
- Name: The subdomain or @ for the root domain
|
||||||
|
- Content: The value for the record (IP address, hostname, text)
|
||||||
|
- TTL: Time To Live in seconds
|
||||||
|
- Priority: For MX and SRV records
|
||||||
|
6. Optional settings:
|
||||||
|
- Enable "Auto IP" for dynamic DNS functionality
|
||||||
|
- Enable "Proxied" for Cloudflare-specific features
|
||||||
|
- Add notes for documentation
|
||||||
|
7. Click "Create Record"
|
||||||
|
|
||||||
|
### Editing DNS Records
|
||||||
|
|
||||||
|
1. Navigate to the DNS Records page
|
||||||
|
2. Click the "Edit" button for the record you want to modify
|
||||||
|
3. Update the record information
|
||||||
|
4. Click "Save Changes"
|
||||||
|
|
||||||
|
### Dynamic DNS Updates
|
||||||
|
|
||||||
|
For records with "Auto IP" enabled:
|
||||||
|
|
||||||
|
1. The system will automatically track your public IP address
|
||||||
|
2. When changes are detected, DNS records are updated automatically
|
||||||
|
3. The history of changes can be viewed on the History page
|
||||||
|
|
||||||
|
## Viewing History
|
||||||
|
|
||||||
|
The History page provides a complete audit trail of changes to your DNS records.
|
||||||
|
|
||||||
|
1. Navigate to the History page
|
||||||
|
2. Filter by domain, record, or date range
|
||||||
|
3. View details of each change including:
|
||||||
|
- Previous value
|
||||||
|
- New value
|
||||||
|
- Timestamp
|
||||||
|
- User who made the change
|
||||||
|
|
||||||
|
## Analyzing Metrics
|
||||||
|
|
||||||
|
The Metrics page provides insights into DNS performance and usage.
|
||||||
|
|
||||||
|
1. Navigate to the Metrics page
|
||||||
|
2. Select the time period for analysis
|
||||||
|
3. View metrics by:
|
||||||
|
- Domain
|
||||||
|
- Record type
|
||||||
|
- Update frequency
|
||||||
|
- Success/failure rates
|
||||||
|
|
||||||
|
## Configuring Webhooks
|
||||||
|
|
||||||
|
Webhooks allow external applications to receive notifications about DNS changes.
|
||||||
|
|
||||||
|
### Creating a Webhook
|
||||||
|
|
||||||
|
1. Navigate to the Webhooks page
|
||||||
|
2. Click "Add Webhook"
|
||||||
|
3. Configure the webhook:
|
||||||
|
- Name: For identification
|
||||||
|
- URL: The endpoint that will receive webhook data
|
||||||
|
- Secret: Used to verify webhook authenticity
|
||||||
|
- Events: Select which events trigger the webhook
|
||||||
|
4. Click "Create Webhook"
|
||||||
|
|
||||||
|
### Testing Webhooks
|
||||||
|
|
||||||
|
1. Navigate to the Webhooks page
|
||||||
|
2. Select a webhook
|
||||||
|
3. Click "Test Webhook"
|
||||||
|
4. View the delivery status and response
|
||||||
|
|
||||||
|
## Managing API Tokens
|
||||||
|
|
||||||
|
API tokens allow programmatic access to the DynamoDNS API.
|
||||||
|
|
||||||
|
### Creating an API Token
|
||||||
|
|
||||||
|
1. Navigate to the API Tokens page
|
||||||
|
2. Click "Create Token"
|
||||||
|
3. Configure the token:
|
||||||
|
- Name: For identification
|
||||||
|
- Expiration: When the token should expire
|
||||||
|
- Access level: Which customers the token can access
|
||||||
|
- Role: What permissions the token has
|
||||||
|
4. Click "Create Token"
|
||||||
|
5. Save the displayed token securely (it will only be shown once)
|
||||||
|
|
||||||
|
### Revoking API Tokens
|
||||||
|
|
||||||
|
1. Navigate to the API Tokens page
|
||||||
|
2. Click "Revoke" next to the token you want to disable
|
||||||
|
3. Confirm the action
|
||||||
|
|
||||||
|
## User Management
|
||||||
|
|
||||||
|
### Managing Your Account
|
||||||
|
|
||||||
|
1. Navigate to Settings → Account tab
|
||||||
|
2. Update your profile information
|
||||||
|
3. Change your password
|
||||||
|
4. Configure two-factor authentication (if available)
|
||||||
|
|
||||||
|
### Managing Users (Admin Only)
|
||||||
|
|
||||||
|
1. Navigate to Users & Roles page
|
||||||
|
2. View all users in the system
|
||||||
|
3. Create new users by clicking "Add User"
|
||||||
|
4. Edit user details by clicking "Edit"
|
||||||
|
5. Disable users by toggling the "Active" status
|
||||||
|
|
||||||
|
## Role Management
|
||||||
|
|
||||||
|
Roles determine what actions users can perform in the system.
|
||||||
|
|
||||||
|
### System Roles
|
||||||
|
|
||||||
|
- **Admin**: Complete access to all features
|
||||||
|
- **Manager**: Can manage customers, domains, and DNS records
|
||||||
|
- **User**: Can manage assigned domains and DNS records
|
||||||
|
- **ReadOnly**: View-only access to assigned resources
|
||||||
|
|
||||||
|
### Custom Roles (Admin Only)
|
||||||
|
|
||||||
|
1. Navigate to Users & Roles page
|
||||||
|
2. Click on the "Roles" tab
|
||||||
|
3. Click "Create Custom Role"
|
||||||
|
4. Configure permissions for the role
|
||||||
|
5. Assign users to the custom role
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **DNS Propagation Delays**: DNS changes may take time to propagate (up to 48 hours, though typically much faster)
|
||||||
|
2. **Provider API Limitations**: Some DNS providers have rate limits or restrictions
|
||||||
|
3. **Authentication Errors**: Check your credentials for the DNS provider
|
||||||
|
|
||||||
|
### Getting Support
|
||||||
|
|
||||||
|
If you encounter issues:
|
||||||
|
|
||||||
|
1. Check the detailed error message
|
||||||
|
2. Review the documentation
|
||||||
|
3. Contact system administrators for assistance
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
- Regularly review and clean up unused DNS records
|
||||||
|
- Use descriptive names and notes for records
|
||||||
|
- Set appropriate TTL values based on your needs
|
||||||
|
- Use API tokens with the minimum necessary permissions
|
||||||
|
- Regularly rotate API tokens for security
|
||||||
|
- Configure webhooks for important events to maintain awareness
|
||||||
|
- Review the history log periodically to audit changes
|
||||||
Reference in New Issue
Block a user