π Self-hosted TOTP authenticator designed for teams and personal use
Features β’ Quick Start β’ Deployment β’ Configuration
- Self-hosted - Your secrets stay on your infrastructure
- Encrypted storage - All TOTP secrets encrypted at rest (AES-256)
- Role-based access - Admin and User roles with fine-grained permissions
- Session management - Secure JWT-based authentication (24h sessions)
- Audit logging - Track all account operations with detailed logs
- Team accounts - Share TOTP codes with your team
- Private accounts - Keep personal authenticators private
- Dynamic visibility - Switch between team/private modes
- User management - Admins can create/manage team members
- Real-time TOTP generation - Live countdown timers with visual indicators
- Brand icons - Auto-detection for 2,800+ services (GitHub, Google, AWS, etc.)
- Favorite system - Star important accounts for quick access
- Skeleton loaders - Beautiful loading states with shimmer animations
- Quick search - Find accounts instantly
- Issuer filtering - Filter by service provider
- QR code import - Upload or paste QR codes
- Manual entry - Add accounts via secret key
- One-click copy - Copy codes with single click
- Responsive design - Works on desktop, tablet, and mobile
- Docker Compose - Deploy in 60 seconds
- Single binary - No complex dependencies
- SQLite database - No external database required
- Automatic backups - Download complete database backups
- Environment variables - Simple configuration
For corporate/production deployments (TRT, enterprises, organizations):
π TRT Deployment Guide - Complete corporate deployment with SSL, backup, monitoring
β‘ TRT Quick Start - 60-minute production deployment guide
Includes:
- SSL/HTTPS setup with corporate certificates
- Nginx reverse proxy configuration
- Automated backup strategies
- User management workflows
- Security hardening
- Audit logging and monitoring
- Docker and Docker Compose installed
- Linux/macOS/Windows with Docker support
- Port 3000 available (or configure custom port)
git clone https://github.com/alameddinc/otto-tp.git
cd otto-tpcp .env.example .envEdit .env to customize:
# Admin credentials (CHANGE IN PRODUCTION!)
ADMIN_PASSWORD=your-secure-admin-password
# Security keys (GENERATE RANDOM 32+ character strings!)
JWT_SECRET=your-jwt-secret-key-change-in-production
ENCRYPTION_KEY=your-encryption-key-32-chars-minimumdocker-compose up -dOpen your browser and navigate to:
http://localhost:3000
Default credentials:
- Username:
admin - Password:
admin(or your configuredADMIN_PASSWORD)
Perfect for home labs, family use, or small teams.
# Clone and start
git clone https://github.com/alameddinc/otto-tp.git
cd otto-tp
docker-compose up -d
# Access via local network
# Example: http://192.168.1.100:3000Recommended:
- Set up reverse proxy (Nginx/Caddy) for HTTPS
- Configure firewall rules
- Set up automatic backups (cron job)
Deploy on any cloud provider with Docker support.
# 1. Launch EC2 instance (Ubuntu 22.04 LTS, t2.micro or larger)
# 2. Connect via SSH
ssh -i your-key.pem ubuntu@your-ec2-ip
# 3. Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
# 4. Install Docker Compose
sudo apt update
sudo apt install docker-compose -y
# 5. Clone and deploy
git clone https://github.com/alameddinc/otto-tp.git
cd otto-tp
# 6. Configure environment
cp .env.example .env
nano .env # Edit passwords and secrets
# 7. Start application
docker-compose up -d
# 8. Configure security group
# Open port 3000 (or your custom port) in AWS Security Group
# Recommended: Use ALB/NLB with SSL certificate# 1. Create Droplet (Docker image, $6/month or larger)
# 2. SSH into droplet
ssh root@your-droplet-ip
# 3. Clone and deploy
git clone https://github.com/alameddinc/otto-tp.git
cd otto-tp
# 4. Configure
cp .env.example .env
nano .env
# 5. Start
docker-compose up -d
# 6. Access via droplet IP
# Example: http://your-droplet-ip:3000For production deployments with HTTPS.
Nginx Configuration:
server {
listen 80;
server_name totp.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name totp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/totp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/totp.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
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;
}
}Caddy Configuration (Automatic HTTPS):
totp.yourdomain.com {
reverse_proxy localhost:3000
}# docker-compose.yml
services:
authenticator:
build:
context: .
dockerfile: Dockerfile.simple
container_name: otto-tp
ports:
- "8080:3000" # Custom port
volumes:
- ./data:/app/data
environment:
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- JWT_SECRET=${JWT_SECRET}
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
restart: unless-stopped| Variable | Required | Default | Description |
|---|---|---|---|
ADMIN_PASSWORD |
Yes | admin |
Admin user password (CHANGE IN PRODUCTION!) |
JWT_SECRET |
Yes | Random | JWT signing secret (32+ chars recommended) |
ENCRYPTION_KEY |
Yes | Random | TOTP secret encryption key (32 chars minimum) |
PORT |
No | 3000 |
Application port |
NODE_ENV |
No | production |
Node environment |
-
Change default passwords immediately
# Generate strong passwords openssl rand -base64 24 -
Use strong encryption keys
# Generate 32-character encryption key openssl rand -hex 32 -
Enable HTTPS in production
- Use reverse proxy (Nginx, Caddy, Traefik)
- Obtain SSL certificate (Let's Encrypt)
-
Restrict network access
- Use firewall rules
- VPN for remote access
- IP whitelisting
-
Regular backups
- Download database backups via Admin menu
- Automate backups with cron jobs
# Example backup script 0 2 * * * docker exec otto-tp sqlite3 /app/data/app.db ".backup /app/data/backup-$(date +\%Y\%m\%d).db"
- Login as admin
- Click Settings (βοΈ) β Download Backup
- Save
.dbfile securely
#!/bin/bash
# backup-otto-tp.sh
BACKUP_DIR="/backups/otto-tp"
DATE=$(date +%Y%m%d-%H%M%S)
CONTAINER="otto-tp"
mkdir -p $BACKUP_DIR
docker exec $CONTAINER sqlite3 /app/data/app.db ".backup /app/data/backup-$DATE.db"
docker cp $CONTAINER:/app/data/backup-$DATE.db $BACKUP_DIR/
docker exec $CONTAINER rm /app/data/backup-$DATE.db
# Keep only last 30 days
find $BACKUP_DIR -name "backup-*.db" -mtime +30 -delete
echo "Backup completed: $BACKUP_DIR/backup-$DATE.db"Add to cron:
crontab -e
# Daily at 2 AM
0 2 * * * /path/to/backup-otto-tp.shOtto-TP provides REST APIs for programmatic access to TOTP codes and account management. Only admin users can create and use API keys.
- Login as admin user
- Navigate to API Keys page (from dashboard)
- Create a new API key with a descriptive name
- Copy the key immediately - it won't be shown again!
All API requests require Bearer token authentication:
curl -H "Authorization: Bearer otto_your_api_key_here" \
https://your-domain.com/api/v1/totp/generate?account_id=123GET /api/v1/totp/generate
Generate a TOTP code for a specific account.
Query Parameters:
account_id(number): Account IDaccount_code(string): Account code in formatissuer:label(e.g.,google:[email protected])
Example Request:
# By account ID
curl -H "Authorization: Bearer otto_abc123..." \
http://localhost:3000/api/v1/totp/generate?account_id=1
# By account code
curl -H "Authorization: Bearer otto_abc123..." \
"http://localhost:3000/api/v1/totp/generate?account_code=google:[email protected]"Example Response:
{
"code": "123456",
"timeRemaining": 25,
"account": {
"id": 1,
"label": "[email protected]",
"issuer": "Google"
}
}GET /api/v1/accounts/export
Export accounts in various formats.
Query Parameters:
format(string):json|csv|otpauth(default:json)filter(string):team|private|all(default:all)include_secrets(boolean):true|false(default:false) - Only for JSON/CSV
Example Requests:
# Export as JSON (without secrets)
curl -H "Authorization: Bearer otto_abc123..." \
http://localhost:3000/api/v1/accounts/export?format=json
# Export as CSV with secrets
curl -H "Authorization: Bearer otto_abc123..." \
"http://localhost:3000/api/v1/accounts/export?format=csv&include_secrets=true" \
-o accounts.csv
# Export as OTPAuth URLs
curl -H "Authorization: Bearer otto_abc123..." \
http://localhost:3000/api/v1/accounts/export?format=otpauthJSON Response Example:
{
"accounts": [
{
"id": 1,
"label": "[email protected]",
"issuer": "Google",
"algorithm": "SHA1",
"digits": 6,
"period": 30,
"visibility": "team",
"created_by": "admin"
}
],
"exported_at": "2025-10-02T12:00:00.000Z",
"total": 1,
"format": "json",
"filter": "all"
}OTPAuth Response Example:
{
"urls": [
"otpauth://totp/Google:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Google&algorithm=SHA1&digits=6&period=30"
],
"exported_at": "2025-10-02T12:00:00.000Z",
"total": 1,
"format": "otpauth",
"filter": "all"
}Integrate TOTP codes into your ETL pipeline for services requiring 2FA:
import requests
import time
API_KEY = "otto_your_api_key_here"
BASE_URL = "http://localhost:3000"
def get_totp_code(account_code):
headers = {"Authorization": f"Bearer {API_KEY}"}
response = requests.get(
f"{BASE_URL}/api/v1/totp/generate",
params={"account_code": account_code},
headers=headers
)
return response.json()["code"]
# Use in ETL process
totp_code = get_totp_code("salesforce:[email protected]")
salesforce_client.login(username, password, totp_code)
# Continue with data extraction...# .github/workflows/deploy.yml
- name: Get TOTP for deployment
run: |
TOTP=$(curl -H "Authorization: Bearer ${{ secrets.OTTO_API_KEY }}" \
"${{ secrets.OTTO_URL }}/api/v1/totp/generate?account_code=aws:deploy-user")
echo "TOTP_CODE=$(echo $TOTP | jq -r '.code')" >> $GITHUB_ENV
- name: Deploy with 2FA
run: |
aws-deploy --totp ${{ env.TOTP_CODE }}#!/bin/bash
# Export all accounts and backup
curl -H "Authorization: Bearer $API_KEY" \
"http://localhost:3000/api/v1/accounts/export?format=json&include_secrets=true" \
-o accounts-backup-$(date +%Y%m%d).json- Admin Only: Only users with
adminrole can create and use API keys - Key Expiration: Set expiration dates for API keys (max 365 days)
- Revocation: Delete API keys instantly from UI
- Visibility Control: API respects account visibility (team/private)
- Rate Limiting: Consider implementing rate limits in production
- HTTPS Only: Always use HTTPS in production environments
cd otto-tp
git pull origin main
docker-compose down
docker-compose build --no-cache
docker-compose up -ddocker logs otto-tp | grep "Next.js"| Username | Role | Default Password |
|---|---|---|
admin |
Admin | admin |
-
Admin
- β Create and manage team accounts (visible to all users)
- β Create and manage private accounts (visible only to themselves)
- β Create and manage users
- β Access audit logs
- β Generate API keys
- β Download database backups
- β Full system access
-
User
- β View all team accounts (created by admins)
- β Create and manage private accounts (visible only to themselves)
- β Star/favorite important accounts
- β Cannot create team accounts
- β Cannot manage users
- β Cannot access audit logs
- β Cannot generate API keys
- Login as
admin - Click Settings (βοΈ) β Manage Users
- Click Add User
- Enter username, password, and role
- Click Create User
# Check logs
docker-compose logs -f
# Restart container
docker-compose restart
# Rebuild from scratch
docker-compose down
docker-compose up -d --build# Reset to default password
docker-compose down
rm -rf ./data
docker-compose up -d# Check what's using port 3000
lsof -i :3000
# Or change port in docker-compose.yml
ports:
- "8080:3000"# Restore from backup
docker-compose down
cp /path/to/backup.db ./data/app.db
docker-compose up -d- IT teams managing service accounts
- DevOps teams sharing infrastructure credentials
- Security teams with shared authenticators
- Support teams accessing customer accounts (with audit trail)
- Startup founders sharing business accounts
- Freelancer teams with client access
- Remote teams with shared services
- Agency teams managing multiple clients
- Family members sharing streaming services
- Couples sharing financial accounts
- Personal backup of authenticators
- Multiple device access to same codes
# Install dependencies
npm install
# Run development server
npm run dev
# Build for production
npm run build
# Run production build
npm startotto-tp/
βββ app/ # Next.js 15 app directory
β βββ api/ # API routes
β βββ dashboard/ # Dashboard page
β βββ page.tsx # Login page
βββ components/ # React components
β βββ ui/ # shadcn/ui components
β βββ *.tsx # Custom components
βββ lib/ # Utilities and libraries
β βββ db/ # Database schema and queries
β βββ auth/ # Authentication logic
β βββ totp/ # TOTP generation
βββ data/ # SQLite database (created on first run)
βββ docker-compose.yml # Docker Compose config
βββ Dockerfile.simple # Production Dockerfile
βββ README.md # This file
MIT License - see LICENSE file for details
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Developed with β€οΈ as open source by Alameddin Γelik
Free Palestine π΅πΈ
- Issues: GitHub Issues
- Discussions: GitHub Discussions
β If you find this project useful, please consider giving it a star! β