diff --git a/aerc/.config/aerc/accounts.conf b/aerc/.config/aerc/accounts.conf index c0a4d5d..aaee9e3 100644 --- a/aerc/.config/aerc/accounts.conf +++ b/aerc/.config/aerc/accounts.conf @@ -9,16 +9,16 @@ postpone = Drafts folders-sort = INBOX,Draftr,Sent,Archive,Spam,Trash aliases = pw@liphlink.xyz,p.waibel@liphlink.xyz,philipp.waibel@liphlink.xyz -[phil_notmuch] -source = notmuch://~/Mail/phil -query-map = ~/.config/aerc/notmuch-queries.conf -# outgoing = smtp://phil%40liphlink.xyz@mail.liphlink.xyz:587 -# outgoing-cred-cmd = pass show mail/phil@liphlink.xyz -from = Phil -default = Inbox -# copy-to = Sent -postpone = Drafts -aliases = pw@liphlink.xyz,p.waibel@liphlink.xyz,philipp.waibel@liphlink.xyz +# [phil_notmuch] +# source = notmuch://~/Mail/phil +# query-map = ~/.config/aerc/notmuch-queries.conf +# # outgoing = smtp://phil%40liphlink.xyz@mail.liphlink.xyz:587 +# # outgoing-cred-cmd = pass show mail/phil@liphlink.xyz +# from = Phil +# default = Inbox +# # copy-to = Sent +# postpone = Drafts +# aliases = pw@liphlink.xyz,p.waibel@liphlink.xyz,philipp.waibel@liphlink.xyz [spam_live] source = imaps://spam%40liphlink.xyz:ANZ6JJPBiB7k1c7k@mail.liphlink.xyz:993 @@ -31,15 +31,15 @@ postpone = Drafts folders-sort = INBOX,Drafts,Sent,Archive,Spam,Trash aliases = blue@liphlink.xyz,red@liphlink.xyz -[spam_notmuch] -source = notmuch://~/Mail/spam -query-map = ~/.config/aerc/notmuch-queries.conf -outgoing = smtp://spam%40liphlink.xyz@mail.liphlink.xyz:587 -outgoing-cred-cmd = pass show mail/spam@liphlink.xyz -from = Liph -copy-to = Sent -default = Inbox -aliases = blue@liphlink.xyz,red@liphlink.xyz +# [spam_notmuch] +# source = notmuch://~/Mail/spam +# query-map = ~/.config/aerc/notmuch-queries.conf +# outgoing = smtp://spam%40liphlink.xyz@mail.liphlink.xyz:587 +# outgoing-cred-cmd = pass show mail/spam@liphlink.xyz +# from = Liph +# copy-to = Sent +# default = Inbox +# aliases = blue@liphlink.xyz,red@liphlink.xyz # [proton] # source = imap+insecure://liiph%40protonmail.com:dRvBWYW3uERY6xqXDgJLeQ@127.0.0.1:1144 diff --git a/aerc/.config/aerc/aerc.conf b/aerc/.config/aerc/aerc.conf index 84d73b6..55771bb 100644 --- a/aerc/.config/aerc/aerc.conf +++ b/aerc/.config/aerc/aerc.conf @@ -98,7 +98,7 @@ index-format=notmuch://~/.local/share/mail #index-columns=flags:4,name<20%,subject,date>= border-char-vertical="│" border-char-horizontal="─" -# styleset-name=rose-pine +styleset-name=rose-pine # # Each name in index-columns must have a corresponding column-$name setting. diff --git a/ansible/.gitignore b/ansible/.gitignore new file mode 100644 index 0000000..edf8fc9 --- /dev/null +++ b/ansible/.gitignore @@ -0,0 +1,42 @@ +# Ansible +*.retry +.vault_pass* +/tmp/ +.ansible/ + +# Generated inventory (regenerate with setup.sh) +inventory/hosts.yml +inventory/group_vars/all/vars.yml + +# Keep vault.yml encrypted (DO NOT ignore it - it should be committed encrypted) +# inventory/group_vars/all/vault.yml + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python + +# Virtual environments +venv/ +env/ +ENV/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log + +# Temporary files +*.tmp +*.bak diff --git a/ansible/AGENTS.md b/ansible/AGENTS.md new file mode 100644 index 0000000..1ddb75b --- /dev/null +++ b/ansible/AGENTS.md @@ -0,0 +1,259 @@ +# Agent Guidelines for Ansible Infrastructure Repository + +This repository contains Docker Compose infrastructure configurations for deploying self-hosted productivity services. This document provides guidelines for AI coding agents working in this repository. + +## Project Overview + +**Type:** Docker Compose Infrastructure Project +**Primary Technology:** Docker, Docker Compose +**Purpose:** Deployment configurations for self-hosted productivity stack including Nextcloud, OnlyOffice, Excalidraw, and Obsidian + +## Repository Structure + +``` +/home/liph/programming/ansible/ +└── nextcloud/ + ├── docker-compose.yml # Main orchestration file (5 services) + └── .env # Environment variables +``` + +## Commands + +### Docker Compose Operations + +```bash +# Navigate to service directory +cd nextcloud/ + +# Start all services +docker compose up -d + +# Start specific service +docker compose up -d + +# Stop all services +docker compose down + +# Stop and remove volumes (DESTRUCTIVE) +docker compose down -v + +# View logs for all services +docker compose logs -f + +# View logs for specific service +docker compose logs -f + +# Restart a service +docker compose restart + +# Rebuild and restart service +docker compose up -d --build + +# Validate docker-compose.yml syntax +docker compose config + +# List running services +docker compose ps +``` + +### Service Names +- `excalidraw` - Drawing/whiteboard tool (port 3009) +- `next-db` - PostgreSQL 18 database +- `next` - Nextcloud main application (port 8808) +- `onlyoffice` - Document server (port 8000) +- `obsidian` - Note-taking app (ports 3004-3005) + +### Testing +No automated tests exist. Manual testing workflow: +1. Validate syntax: `docker compose config` +2. Start services: `docker compose up -d` +3. Check health: `docker compose ps` +4. Review logs: `docker compose logs` +5. Test endpoints: `curl localhost:8808` (Nextcloud), etc. + +## Code Style Guidelines + +### YAML Formatting (docker-compose.yml) + +**Indentation:** +- Use 2 spaces for indentation (NO tabs) +- Maintain consistent indentation levels + +**Structure:** +```yaml +services: + service-name: + image: docker.io/image:tag + container_name: container-name + depends_on: + - dependency + ports: + - "host:container" + environment: + - KEY=value + - KEY=${ENV_VAR} + volumes: + - volume_name:/container/path + - ./host/path:/container/path + restart: unless-stopped + networks: + - network_name +``` + +**Naming Conventions:** +- Container names: Use kebab-case (e.g., `next-db`, `next-redis`) +- Service names: Use snake_case or kebab-case consistently +- Volume names: Use snake_case (e.g., `nextcloud_data`, `pg_data`) +- Network names: Use snake_case with project prefix (e.g., `nextcloud_network`) + +**Environment Variables:** +- Reference .env variables using `${VAR_NAME}` syntax +- Never hardcode sensitive data (passwords, secrets) in docker-compose.yml +- Use explicit environment variable declarations with `-` prefix + +**Image Specifications:** +- Always use fully qualified image names: `docker.io/image:tag` +- Pin specific versions for production (avoid `:latest` in production) +- Current exception: development environment uses `:latest` tags + +**Volumes:** +- Named volumes for persistent data (defined in volumes section) +- Bind mounts for configuration files using `./relative/path` +- Always specify volume mount destination path +- CRITICAL: Never leave empty volume definitions (e.g., `- :/path`) + +**Comments:** +- Use `#` for comments +- Add comments above service definitions to describe purpose +- Comment out optional services with `# ` prefix on each line + +### Environment Files (.env) + +**Format:** +```bash +# Database Configuration +DB_PASSWORD=secure_password_here +DB_USERNAME=nextcloud +DB_DATABASE_NAME=nextcloud +DB_HOST=next-db + +# User/Group IDs +PUID=33 +PGID=1000 +``` + +**Rules:** +- One variable per line: `KEY=value` +- No spaces around `=` +- No quotes needed for values +- Group related variables with comment headers +- Never commit sensitive values (use placeholders or .env.example) +- All variables must have values (no empty assignments) + +### Security Guidelines + +1. **Secrets Management:** + - Never hardcode passwords in docker-compose.yml + - Use .env file for credentials (ensure .env is in .gitignore) + - Consider Docker secrets for sensitive production data + - Rotate default passwords immediately + +2. **Current Security Issues to Fix:** + - Line 53 in docker-compose.yml: Remove hardcoded admin password + - .env file: All database credentials are empty + - Consider enabling JWT for OnlyOffice (currently disabled) + +3. **Network Security:** + - Use isolated Docker networks for service communication + - Only expose necessary ports to host + - Consider reverse proxy (nginx/traefik) for HTTPS termination + +### Error Handling + +**Validation Steps Before Committing:** +1. Run `docker compose config` to validate YAML syntax +2. Ensure all volume mount paths are complete +3. Verify all environment variables are defined in .env +4. Check for hardcoded secrets +5. Confirm port conflicts with `docker compose ps` + +**Common Issues:** +- Empty volume definitions: Always specify source and destination +- Missing environment variables: Define all referenced vars in .env +- Port conflicts: Use `docker ps` to check existing port bindings +- Network errors: Ensure services on same network can communicate + +### Configuration Management + +**Volume Mapping Patterns:** +```yaml +# Named volume (recommended for data) +volumes: + - nextcloud_data:/var/www/html + +# Bind mount with SELinux label (for config) +volumes: + - ./config:/var/www/html/config:Z + +# Bind mount with shared label +volumes: + - ./vault:/vault:z +``` + +**Restart Policies:** +- Use `restart: unless-stopped` for production services +- Avoid `restart: always` (harder to stop deliberately) +- Use `restart: on-failure` for development/debugging + +### Database Configuration + +**PostgreSQL Environment Variables:** +- `POSTGRES_DB` - Database name +- `POSTGRES_USER` - Database user +- `POSTGRES_PASSWORD` - Database password + +**Nextcloud Database Connection:** +- `POSTGRES_HOST` - Hostname (service name: `next-db`) +- Must match database service configuration + +### Best Practices + +1. **Service Dependencies:** + - Use `depends_on` to define startup order + - Note: `depends_on` doesn't wait for "ready" state + +2. **Resource Limits:** + - Consider adding memory/CPU limits for production + - Current config uses `mem_swappiness: -1` for Nextcloud + +3. **Timezone Configuration:** + - Set `TZ` environment variable for correct timestamps + - Current: `TZ=Europe/Zurich` (Excalidraw), `TZ=Etc/UTC` (Obsidian) + +4. **Data Persistence:** + - Always use named volumes for important data + - Define volumes in top-level `volumes:` section + - Backup volume data regularly + +5. **Making Changes:** + - Test changes in development before production + - Use `docker compose config` to validate + - Review diff carefully before applying + - Document breaking changes + +## Development Workflow + +1. Make changes to docker-compose.yml or .env +2. Validate: `docker compose config` +3. Apply changes: `docker compose up -d` +4. Verify: `docker compose ps && docker compose logs` +5. Test affected services manually +6. Document changes in commit message + +## Critical Fixes Needed + +- [ ] Complete empty volume mount paths (lines 21, 55-57, 74, 89-90) +- [ ] Remove hardcoded admin password (line 53) +- [ ] Populate database credentials in .env file +- [ ] Add .gitignore to exclude .env from version control +- [ ] Consider adding docker-compose.override.yml for local development diff --git a/ansible/ARCHITECTURE.md b/ansible/ARCHITECTURE.md new file mode 100644 index 0000000..ee4921d --- /dev/null +++ b/ansible/ARCHITECTURE.md @@ -0,0 +1,426 @@ +# Network Architecture + +Visual overview of how all services connect and communicate. + +## 🌐 Network Flow Diagram + +``` + INTERNET + │ + │ DNS A Records + │ (cloud.yourdomain.com → SERVER_IP) + ↓ + ┌───────────────┐ + │ Firewall (UFW)│ + │ Ports: 80 │ + │ 443 │ + │ 41641 │ + └───────┬───────┘ + │ + ┌────────────────┼────────────────┐ + │ │ │ + Port 80/443 Port 41641 Port 22 + │ │ │ + ↓ ↓ ↓ + ┌──────────────┐ ┌─────────────┐ ┌──────────┐ + │ CADDY │ │ TAILSCALE │ │ SSH │ + │ Reverse Proxy│ │ VPN │ │ Access │ + └──────┬───────┘ └─────┬───────┘ └──────────┘ + │ │ + │ │ + ┌──────────┴────────┐ │ + │ │ │ + ↓ ↓ ↓ +┌─────────┐ ┌─────────────────┐ +│ PUBLIC │ │ TAILSCALE-ONLY │ +│SERVICES │ │ SERVICES │ +└─────────┘ └─────────────────┘ +``` + +--- + +## 🔐 Access Matrix + +| Service | Public URL | Tailscale URL | Direct Access | +|---------|-----------|---------------|---------------| +| **Nextcloud** | ✅ https://cloud.domain.com | ✅ Via Tailscale IP | ❌ No | +| **OnlyOffice** | ✅ https://office.domain.com | ✅ Via Tailscale IP | ❌ No | +| **Excalidraw** | ✅ https://draw.domain.com | ✅ Via Tailscale IP | ❌ No | +| **Obsidian** | ✅ https://notes.domain.com | ✅ Via Tailscale IP | ❌ No | +| **Homarr** | ❌ 403 Forbidden | ✅ https://home.domain.com | ❌ No | +| **Dockhand** | ❌ 403 Forbidden | ✅ https://manage.domain.com | ❌ No | +| **Uptime Kuma** | ❌ 403 Forbidden | ✅ https://uptime.domain.com | ❌ No | +| **PostgreSQL** | ❌ No | ❌ No | ✅ Docker network only | +| **Redis** | ❌ No | ❌ No | ✅ Docker network only | +| **Caddy** | ❌ No (serves others) | ❌ No | ✅ Docker network only | +| **Watchtower** | ❌ No | ❌ No | ✅ Docker network only | + +--- + +## 🐳 Docker Network Topology + +``` +┌────────────────────────────────────────────────────────────────┐ +│ nextcloud_network (bridge) │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │PostgreSQL│ │ Redis │ │Nextcloud │ │OnlyOffice│ │ +│ │ :5432 │ │ :6379 │ │ :80 │ │ :80 │ │ +│ └──────────┘ └──────────┘ └────┬─────┘ └──────────┘ │ +│ ↑ ↑ │ │ +│ │ │ │ │ +│ └──────────────┴─────────────┘ │ +│ │ │ +│ ┌──────────┐ ┌────┴─────┐ ┌──────────┐ ┌──────────┐ │ +│ │Excalidraw│ │ Caddy │ │ Obsidian │ │ Homarr │ │ +│ │ :80 │ │80→:80 │ │ :3000 │ │ :7575 │ │ +│ └──────────┘ │443→:443 │ └──────────┘ └────┬─────┘ │ +│ │ │ │ │ +│ ┌──────────┐ │ │ ┌──────────┐ ↓ │ +│ │ Dockhand │ │ │ │ Uptime │ /var/run/ │ +│ │ :3000 │ │ │ │ Kuma │ docker.sock │ +│ └──────────┘ └──────────┘ │ :3001 │ (read-only) │ +│ └──────────┘ │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ Watchtower (monitors all) │ │ +│ │ Accesses: /var/run/docker.sock │ │ +│ └──────────────────────────────────────────────────┘ │ +│ │ +└────────────────────────────────────────────────────────────────┘ + │ │ + │ Exposed Ports │ Internal + │ │ Communication + ↓ ↓ + Host: 80, 443 Container-to-Container + (Caddy only) via Docker DNS +``` + +--- + +## 🔄 Request Flow Examples + +### Example 1: User Accesses Nextcloud + +``` +User Browser + │ + │ HTTPS GET https://cloud.yourdomain.com + ↓ +Internet + │ + ↓ +Firewall (Port 443) + │ + ↓ +Caddy Container (:443) + │ + │ Validates SSL certificate + │ Checks Caddyfile rules + │ Proxies to backend + ↓ +Nextcloud Container (:80) + │ + │ Checks trusted domains + │ Queries PostgreSQL + │ Checks Redis cache + ↓ +PostgreSQL + Redis + │ + │ Returns data + ↓ +Nextcloud → Caddy → User +``` + +### Example 2: User Accesses Homarr (via Tailscale) + +``` +User Browser (on Tailscale) + │ + │ HTTPS GET https://home.yourdomain.com + ↓ +Internet → DNS Resolution + │ + ↓ +Firewall (Port 443) + │ + ↓ +Caddy Container + │ + │ Checks client IP: 100.64.x.x (Tailscale range) + │ ✅ Match! Proxy to backend + │ + ↓ +Homarr Container (:7575) + │ + │ Reads Docker socket + │ Shows container status + ↓ +Returns dashboard → Caddy → User +``` + +### Example 3: User Accesses Homarr (NOT on Tailscale) + +``` +User Browser (public internet) + │ + │ HTTPS GET https://home.yourdomain.com + ↓ +Internet → DNS Resolution + │ + ↓ +Firewall (Port 443) + │ + ↓ +Caddy Container + │ + │ Checks client IP: NOT in 100.64.0.0/10 + │ ❌ No match! Return 403 Forbidden + │ + ↓ +403 Access Denied +``` + +### Example 4: Nextcloud Connects to Database + +``` +Nextcloud Container + │ + │ Docker DNS lookup: next-db + │ Resolves to: 172.20.0.x + ↓ +PostgreSQL Container (next-db:5432) + │ + │ Internal Docker network + │ No external exposure + │ + ↓ +Returns query results +``` + +--- + +## 📊 Data Flow Diagram + +### File Upload to Nextcloud + +``` +User → Caddy → Nextcloud → Storage Volume + │ + ├→ PostgreSQL (metadata) + └→ Redis (cache) +``` + +### Document Editing with OnlyOffice + +``` +User → Caddy → Nextcloud → Caddy → OnlyOffice + │ │ + ↓ ↓ + PostgreSQL Document + (metadata) Processing + │ │ + ↓ ↓ + Nextcloud ←───────── OnlyOffice + │ + ↓ + Storage Volume +``` + +### Watchtower Auto-Update + +``` +Watchtower (cron: every 24h) + │ + │ Check Docker Hub for new images + ↓ +New image available? + │ + ├─ NO → Sleep + │ + ├─ YES → Check container labels + │ + ├─ "enable=false" → Skip + ├─ "enable=true" → Pull & Update + └─ "monitor-only=true" → Notify +``` + +--- + +## 🔐 Security Boundaries + +``` +┌─────────────────────────────────────────────────────────────┐ +│ INTERNET (Untrusted) │ +└────────────────────────┬────────────────────────────────────┘ + │ + ┌────────▼────────┐ + │ UFW Firewall │ ← Layer 1: Host Firewall + │ 22, 80, 443 │ + └────────┬────────┘ + │ + ┌────────▼────────┐ + │ fail2ban │ ← Layer 2: Intrusion Detection + │ SSH Protection │ + └────────┬────────┘ + │ + ┌────────▼────────┐ + │ Caddy (HTTPS) │ ← Layer 3: TLS Termination + │ SSL Validation │ + └────────┬────────┘ + │ + ┌────────────────┼────────────────┐ + │ │ │ + ┌───▼────┐ ┌────▼────┐ ┌─────▼─────┐ + │ Public │ │Tailscale│ │ Docker │ ← Layer 4: Network + │Services│ │ Check │ │ Network │ Isolation + └────────┘ └─────────┘ └───────────┘ + │ + ┌────▼────┐ + │ Admin │ ← Layer 5: Admin Access + │ Services│ (Tailscale VPN only) + └─────────┘ +``` + +--- + +## 🗄️ Data Persistence + +### Docker Volumes + +``` +Host Filesystem + │ + ├── /var/lib/docker/volumes/ + │ ├── nextcloud_pg_data/ ← PostgreSQL database + │ ├── nextcloud_redis_data/ ← Redis cache + │ ├── nextcloud_nextcloud_data/ ← Nextcloud files + │ ├── nextcloud_nextcloud_apps/ ← Nextcloud apps + │ ├── nextcloud_onlyoffice_data/ ← OnlyOffice docs + │ ├── nextcloud_caddy_data/ ← SSL certificates + │ ├── nextcloud_caddy_config/ ← Caddy config + │ ├── nextcloud_dockhand_data/ ← Dockhand settings + │ └── nextcloud_uptime_kuma_data/ ← Uptime Kuma data + │ + └── /opt/nextcloud-stack/ + ├── configs/ + │ ├── caddy/Caddyfile + │ └── nextcloud/ + ├── data/ + │ ├── homarr/ + │ └── obsidian/ + └── backups/ + ├── database/ + └── volumes/ +``` + +--- + +## 🔄 Update Mechanism + +### Watchtower Label-Based Control + +```yaml +# Auto-update allowed +labels: + - "com.centurylinklabs.watchtower.enable=true" +→ Caddy, Excalidraw, Obsidian, Homarr, Dockhand, Uptime Kuma + +# Monitor only (notify, no update) +labels: + - "com.centurylinklabs.watchtower.monitor-only=true" +→ OnlyOffice + +# Never auto-update (manual only) +labels: + - "com.centurylinklabs.watchtower.enable=false" +→ Nextcloud, PostgreSQL, Redis +``` + +--- + +## 📡 Monitoring Architecture + +``` +┌────────────────────────────────────────────────────────┐ +│ Uptime Kuma │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ HTTP Monitors (every 60s) │ │ +│ │ • https://cloud.yourdomain.com/status.php │ │ +│ │ • https://office.yourdomain.com/health │ │ +│ │ • https://draw.yourdomain.com │ │ +│ └──────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ TCP Port Monitors │ │ +│ │ • next-db:5432 (PostgreSQL) │ │ +│ │ • next-redis:6379 (Redis) │ │ +│ └──────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ SSL Certificate Monitor │ │ +│ │ • Expiry check (30-day warning) │ │ +│ └──────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ Notifications │ │ +│ │ • Email alerts │ │ +│ │ • Slack/Discord webhooks (optional) │ │ +│ └──────────────────────────────────────────────┘ │ +└────────────────────────────────────────────────────────┘ +``` + +--- + +## 🎯 Service Dependencies + +``` +Nextcloud + │ + ├─ requires → PostgreSQL (healthy) + ├─ requires → Redis (healthy) + └─ requires → Caddy (for external access) + +OnlyOffice + │ + └─ requires → Caddy (for external access) + +Homarr, Dockhand + │ + ├─ requires → Docker Socket (read-only) + └─ requires → Caddy (for Tailscale access) + +Watchtower + │ + └─ requires → Docker Socket (read-write) + +All Services + │ + └─ network → nextcloud_network +``` + +--- + +## 🌟 Architecture Benefits + +### High Availability Features +- **Health checks**: Containers auto-restart on failure +- **Database connection pooling**: Redis caching reduces DB load +- **SSL auto-renewal**: Caddy handles certificate lifecycle + +### Security Layers +1. **Network**: UFW firewall + fail2ban +2. **Transport**: TLS/SSL via Caddy +3. **Access**: Tailscale VPN for admin interfaces +4. **Secrets**: Ansible Vault encryption +5. **Isolation**: Docker network segmentation + +### Scalability Points +- **Database**: Can migrate to external PostgreSQL +- **Cache**: Redis can be scaled/clustered +- **Storage**: Volumes can be moved to network storage +- **Reverse Proxy**: Caddy can be load-balanced + +--- + +**This architecture provides a secure, maintainable, and production-ready self-hosted cloud platform.** diff --git a/ansible/BACKUP_RESTORE.md b/ansible/BACKUP_RESTORE.md new file mode 100644 index 0000000..0aa19d1 --- /dev/null +++ b/ansible/BACKUP_RESTORE.md @@ -0,0 +1,420 @@ +# Backup and Restore Guide + +Complete guide for backing up and restoring your Nextcloud Stack. + +## Automated Backups + +### What Gets Backed Up + +- **Daily (3:00 AM)**: + - PostgreSQL database dump + +- **Weekly (Sundays, 3:00 AM)**: + - Nextcloud data volume + - Configuration files + +- **Retention**: 30 days + +### Backup Locations + +``` +/opt/nextcloud-stack/backups/ +├── database/ +│ └── nextcloud_db_YYYYMMDD_HHMMSS.sql.gz +├── volumes/ +│ ├── nextcloud_data_YYYYMMDD_HHMMSS.tar.gz +│ └── configs_YYYYMMDD_HHMMSS.tar.gz +└── backup.log +``` + +### Manual Backup + +```bash +ssh user@server +/opt/nextcloud-stack/backup.sh +``` + +### Check Backup Status + +```bash +# View backup log +tail -f /opt/nextcloud-stack/backups/backup.log + +# List backups +ls -lh /opt/nextcloud-stack/backups/database/ +ls -lh /opt/nextcloud-stack/backups/volumes/ + +# Check disk usage +du -sh /opt/nextcloud-stack/backups/ +``` + +--- + +## Restore Procedures + +### 1. Restore Database Only + +**When to use:** +- Database corruption +- Accidental data deletion +- Need to revert to earlier state + +**Steps:** + +```bash +# 1. Stop Nextcloud (keep database running) +cd /opt/nextcloud-stack +docker compose stop next + +# 2. List available backups +ls -lh backups/database/ + +# 3. Choose backup to restore +BACKUP_FILE="backups/database/nextcloud_db_20260216_030000.sql.gz" + +# 4. Drop existing database (CAUTION!) +docker exec next-db psql -U nextcloud -c "DROP DATABASE nextcloud;" +docker exec next-db psql -U nextcloud -c "CREATE DATABASE nextcloud;" + +# 5. Restore from backup +gunzip < $BACKUP_FILE | docker exec -i next-db psql -U nextcloud -d nextcloud + +# 6. Restart Nextcloud +docker compose start next + +# 7. Run Nextcloud upgrade (if needed) +docker exec -u www-data next php occ upgrade + +# 8. Disable maintenance mode +docker exec -u www-data next php occ maintenance:mode --off +``` + +### 2. Restore Data Volumes + +**When to use:** +- Lost files +- Corrupted data directory +- Complete system failure + +**Steps:** + +```bash +# 1. Stop all services +cd /opt/nextcloud-stack +docker compose down + +# 2. List available backups +ls -lh backups/volumes/ + +# 3. Choose backup +BACKUP_FILE="backups/volumes/nextcloud_data_20260216_030000.tar.gz" + +# 4. Restore volume +# Note: This requires accessing the Docker volume directory +sudo tar -xzf $BACKUP_FILE -C /var/lib/docker/volumes/nextcloud_nextcloud_data/_data/ + +# 5. Restore configs (optional) +CONFIG_BACKUP="backups/volumes/configs_20260216_030000.tar.gz" +sudo tar -xzf $CONFIG_BACKUP -C /opt/nextcloud-stack/configs/ + +# 6. Fix permissions +sudo chown -R www-data:www-data /var/lib/docker/volumes/nextcloud_nextcloud_data/_data/ + +# 7. Start services +docker compose up -d + +# 8. Run Nextcloud file scan +docker exec -u www-data next php occ files:scan --all +``` + +### 3. Complete System Restore + +**When to use:** +- Disaster recovery +- Migration to new server +- Complete system failure + +**Steps:** + +```bash +# 1. On new server, install base system +# Run Ansible playbooks 01-04 (up to Tailscale) +ansible-playbook playbooks/01-preflight-checks.yml --ask-vault-pass +ansible-playbook playbooks/02-system-setup.yml --ask-vault-pass +ansible-playbook playbooks/03-docker-setup.yml --ask-vault-pass +ansible-playbook playbooks/04-tailscale-setup.yml --ask-vault-pass + +# 2. Create deployment directory structure +ssh user@new-server +sudo mkdir -p /opt/nextcloud-stack/backups/{database,volumes} + +# 3. Copy backups from old server to new server +# On your local machine: +scp -r old-server:/opt/nextcloud-stack/backups/* user@new-server:/opt/nextcloud-stack/backups/ + +# 4. Deploy stack (creates volumes and containers) +ansible-playbook playbooks/05-deploy-stack.yml --ask-vault-pass + +# 5. Stop services on new server +ssh user@new-server +cd /opt/nextcloud-stack +docker compose down + +# 6. Restore database +BACKUP_FILE="backups/database/nextcloud_db_20260216_030000.sql.gz" +docker compose up -d next-db next-redis +sleep 10 +gunzip < $BACKUP_FILE | docker exec -i next-db psql -U nextcloud -d nextcloud + +# 7. Restore data volumes +VOLUME_BACKUP="backups/volumes/nextcloud_data_20260216_030000.tar.gz" +sudo tar -xzf $VOLUME_BACKUP -C /var/lib/docker/volumes/nextcloud_nextcloud_data/_data/ + +# 8. Restore configs +CONFIG_BACKUP="backups/volumes/configs_20260216_030000.tar.gz" +sudo tar -xzf $CONFIG_BACKUP -C /opt/nextcloud-stack/configs/ + +# 9. Fix permissions +sudo chown -R www-data:www-data /var/lib/docker/volumes/nextcloud_nextcloud_data/_data/ + +# 10. Start all services +docker compose up -d + +# 11. Run Nextcloud maintenance +docker exec -u www-data next php occ maintenance:mode --off +docker exec -u www-data next php occ files:scan --all +docker exec -u www-data next php occ db:add-missing-indices + +# 12. Continue with remaining playbooks +exit +ansible-playbook playbooks/06-configure-caddy.yml --ask-vault-pass +ansible-playbook playbooks/07-setup-backups.yml --ask-vault-pass +ansible-playbook playbooks/08-post-deployment.yml --ask-vault-pass +``` + +--- + +## Off-Site Backups with rclone + +### Initial Setup + +```bash +ssh user@server + +# Configure rclone +rclone config + +# Example: Setup Backblaze B2 +# Follow prompts: +# - Choose: New remote +# - Name: b2backup +# - Storage: Backblaze B2 +# - Enter account ID and application key +``` + +### Sync Backups to Remote + +```bash +# Test sync (dry run) +rclone sync /opt/nextcloud-stack/backups/ b2backup:nextcloud-backups --dry-run + +# Actual sync +rclone sync /opt/nextcloud-stack/backups/ b2backup:nextcloud-backups +``` + +### Automated Off-Site Backups + +Add to `/opt/nextcloud-stack/backup.sh` (after the cleanup section): + +```bash +# Off-site backup (if rclone configured) +if command -v rclone &> /dev/null && rclone listremotes | grep -q "b2backup"; then + log "Syncing backups to off-site storage..." + rclone sync $BACKUP_DIR b2backup:nextcloud-backups --log-file=$LOG_FILE + log "Off-site sync completed" +fi +``` + +### Restore from Off-Site Backup + +```bash +# List remote backups +rclone ls b2backup:nextcloud-backups/database/ + +# Download specific backup +rclone copy b2backup:nextcloud-backups/database/nextcloud_db_20260216_030000.sql.gz /opt/nextcloud-stack/backups/database/ + +# Download all backups +rclone sync b2backup:nextcloud-backups /opt/nextcloud-stack/backups/ +``` + +--- + +## Backup Verification + +### Test Database Backup Integrity + +```bash +# 1. Extract backup +gunzip -c backups/database/nextcloud_db_20260216_030000.sql.gz > /tmp/test_restore.sql + +# 2. Check for errors +grep -i "error" /tmp/test_restore.sql + +# 3. Verify size (should be reasonable) +ls -lh /tmp/test_restore.sql + +# 4. Cleanup +rm /tmp/test_restore.sql +``` + +### Test Volume Backup Integrity + +```bash +# Test tar archive +tar -tzf backups/volumes/nextcloud_data_20260216_030000.tar.gz | head -20 + +# Check for errors +tar -tzf backups/volumes/nextcloud_data_20260216_030000.tar.gz > /dev/null && echo "Archive OK" +``` + +--- + +## Migration to New Server + +**Complete migration guide:** + +1. **Prepare new server:** + - Same or newer Ubuntu version + - Run Ansible setup playbooks (01-04) + +2. **Backup old server:** + ```bash + /opt/nextcloud-stack/backup.sh + ``` + +3. **Copy backups to new server:** + ```bash + rsync -avz old-server:/opt/nextcloud-stack/backups/ new-server:/opt/nextcloud-stack/backups/ + ``` + +4. **Update DNS:** + - Point all domains to new server IP + - Wait for propagation + +5. **Restore on new server:** + - Follow "Complete System Restore" steps above + +6. **Verify:** + - Test all services + - Check Nextcloud functionality + - Verify SSL certificates + +7. **Decommission old server:** + - Only after confirming new server works + - Keep final backup from old server + +--- + +## Backup Best Practices + +### DO: +- ✅ Test restores regularly (monthly) +- ✅ Keep backups off-site (rclone to cloud storage) +- ✅ Verify backup integrity +- ✅ Monitor backup log for errors +- ✅ Document restore procedures +- ✅ Keep multiple backup generations + +### DON'T: +- ❌ Store backups only on same server +- ❌ Assume backups work without testing +- ❌ Delete old backups without verification +- ❌ Skip database backups +- ❌ Ignore backup failure notifications + +--- + +## Backup Schedule Customization + +Edit `/opt/nextcloud-stack/backup.sh` to change: + +- Backup frequency +- Retention period +- What gets backed up +- Compression settings + +Edit cron job: +```bash +sudo crontab -e + +# Change from 3:00 AM to 2:00 AM +0 2 * * * /opt/nextcloud-stack/backup.sh >> /opt/nextcloud-stack/backups/backup.log 2>&1 +``` + +--- + +## Troubleshooting Backups + +### Backup script fails + +**Check logs:** +```bash +tail -100 /opt/nextcloud-stack/backups/backup.log +``` + +**Common issues:** +- Disk space full +- Docker container not running +- Permission denied + +**Solutions:** +```bash +# Check disk space +df -h + +# Check containers +docker ps + +# Fix permissions +sudo chown -R root:root /opt/nextcloud-stack/backup.sh +sudo chmod +x /opt/nextcloud-stack/backup.sh +``` + +### Database backup empty + +**Verify database is running:** +```bash +docker exec next-db pg_isready -U nextcloud +``` + +**Test manual backup:** +```bash +docker exec next-db pg_dump -U nextcloud nextcloud > /tmp/test.sql +ls -lh /tmp/test.sql +``` + +--- + +## Emergency Recovery + +If all backups are lost and you need to start fresh: + +```bash +# 1. Remove everything +ansible-playbook playbooks/99-rollback.yml --ask-vault-pass +cd /opt/nextcloud-stack +docker compose down -v + +# 2. Redeploy from scratch +ansible-playbook playbooks/site.yml --ask-vault-pass + +# 3. Reconfigure Nextcloud manually +# Login and set up users, apps, etc. +``` + +--- + +**Remember:** Backups are worthless unless you've tested restoring from them! + +**Last Updated:** 2026-02-16 diff --git a/ansible/DEPLOYMENT_GUIDE.md b/ansible/DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..dd58669 --- /dev/null +++ b/ansible/DEPLOYMENT_GUIDE.md @@ -0,0 +1,470 @@ +# Quick Deployment Guide + +Get your Nextcloud Stack running in under an hour! + +## ⚡ Quick Start (3 Steps) + +### Step 1: Configure (5-10 minutes) + +```bash +./setup.sh +``` + +Answer the questions about your servers and preferences. This generates your encrypted configuration. + +### Step 2: Deploy (30-45 minutes per server) + +```bash +make deploy +``` + +Or manually: +```bash +ansible-playbook playbooks/site.yml --ask-vault-pass +``` + +### Step 3: Access Your Services + +- **Nextcloud**: `https://cloud.yourdomain.com` +- **OnlyOffice**: `https://office.yourdomain.com` +- **Excalidraw**: `https://draw.yourdomain.com` +- **Obsidian**: `https://notes.yourdomain.com` + +**Management (Tailscale only)**: +- **Homarr Dashboard**: `https://home.yourdomain.com` +- **Dockhand**: `https://manage.yourdomain.com` +- **Uptime Kuma**: `https://uptime.yourdomain.com` + +--- + +## 📋 Prerequisites Checklist + +### Before You Begin + +- [ ] Ubuntu 20.04+ server (LXC or VPS) +- [ ] Root or sudo access +- [ ] Minimum 100GB disk space +- [ ] Ansible 2.14+ on your control machine +- [ ] Domain name with DNS access + +### DNS Configuration (CRITICAL!) + +Before deployment, create these A records pointing to your server IP: + +``` +cloud.yourdomain.com → YOUR_SERVER_IP +office.yourdomain.com → YOUR_SERVER_IP +draw.yourdomain.com → YOUR_SERVER_IP +notes.yourdomain.com → YOUR_SERVER_IP +home.yourdomain.com → YOUR_SERVER_IP +manage.yourdomain.com → YOUR_SERVER_IP +uptime.yourdomain.com → YOUR_SERVER_IP +``` + +**Verify DNS before deployment:** +```bash +dig +short cloud.yourdomain.com +# Should return: YOUR_SERVER_IP +``` + +--- + +## 🎯 What Gets Deployed + +### 12 Services + +| Service | Purpose | Auto-Update | +|---------|---------|-------------| +| **Nextcloud** | File sync & collaboration | ❌ Manual | +| **PostgreSQL 18** | Database | ❌ Manual | +| **Redis 7** | Cache | ❌ Manual | +| **OnlyOffice** | Document editor | 👁️ Monitor | +| **Excalidraw** | Whiteboard | ✅ Auto | +| **Obsidian** | Notes | ✅ Auto | +| **Caddy** | Reverse proxy + SSL | ✅ Auto | +| **Homarr** | Dashboard | ✅ Auto | +| **Dockhand** | Container manager | ✅ Auto | +| **Uptime Kuma** | Monitoring | ✅ Auto | +| **Watchtower** | Auto-updater | N/A | + +### Security Features + +- ✅ UFW firewall configured +- ✅ Fail2ban for SSH protection +- ✅ Automatic SSL certificates (Let's Encrypt) +- ✅ Ansible Vault encrypted secrets +- ✅ Tailscale-only admin interfaces +- ✅ Automatic security updates + +### Backup System + +- **Daily**: Database backups (3:00 AM) +- **Weekly**: Volume backups (Sundays) +- **Retention**: 30 days +- **Location**: `/opt/nextcloud-stack/backups/` + +--- + +## 📝 Detailed Setup Process + +### 1. Install Ansible (Control Machine) + +**Ubuntu/Debian:** +```bash +sudo apt update +sudo apt install ansible +``` + +**macOS:** +```bash +brew install ansible +``` + +**Verify:** +```bash +ansible --version +# Should be 2.14 or higher +``` + +### 2. Clone Repository + +```bash +git clone +cd ansible-nextcloud-deployment +``` + +### 3. Run Interactive Setup + +```bash +chmod +x setup.sh +./setup.sh +``` + +**You'll be asked for:** + +1. **Server Details** (for each server): + - IP address + - Hostname + - Domain (e.g., `example.com`) + - SSH user + - SSH key path + +2. **User Information**: + - Your name + - Your email (for SSL certificates) + - Timezone + +3. **Admin Account**: + - Nextcloud admin username + - Nextcloud admin password + +4. **Subdomain Preferences** (defaults shown): + - Nextcloud: `cloud` + - OnlyOffice: `office` + - Excalidraw: `draw` + - Obsidian: `notes` + - Homarr: `home` + - Dockhand: `manage` + - Uptime Kuma: `uptime` + +5. **Tailscale** (optional): + - Auth key (or skip for manual activation) + +6. **Monitoring**: + - Alert email + - Public status page (yes/no) + +7. **Backups**: + - Install rclone (yes/no) + +8. **Ansible Vault Password**: + - Create a password to encrypt secrets + +**Output:** +- `inventory/hosts.yml` - Server inventory +- `inventory/group_vars/all/vars.yml` - Public variables +- `inventory/group_vars/all/vault.yml` - Encrypted secrets + +### 4. Test Connectivity + +```bash +make ping +``` + +Or: +```bash +ansible all -m ping --ask-vault-pass +``` + +Expected output: +``` +server-hostname | SUCCESS => { + "ping": "pong" +} +``` + +### 5. Run Deployment + +```bash +make deploy +``` + +Or manually: +```bash +ansible-playbook playbooks/site.yml --ask-vault-pass +``` + +**What happens** (30-45 minutes): + +1. ✅ **Preflight Checks** (2 min) + - Validates DNS, connectivity, disk space + +2. ⚙️ **System Setup** (10-15 min) + - Installs packages + - Configures firewall (UFW) + - Sets up fail2ban + +3. 🐳 **Docker Setup** (5 min) + - Removes old Docker + - Installs Docker CE + Compose v2 + +4. 🔐 **Tailscale** (2 min) + - Installs Tailscale + - Activates if auth key provided + +5. 📦 **Deploy Stack** (10-15 min) + - Templates configuration files + - Pulls Docker images + - Starts all containers + - Initializes Nextcloud + +6. 🌐 **Configure Caddy** (2-5 min) + - Validates configuration + - Obtains SSL certificates + +7. 💾 **Setup Backups** (2 min) + - Creates backup script + - Sets up cron jobs + +8. ✅ **Post-Deployment** (5 min) + - Verifies all services + - Installs Nextcloud apps + - Creates deployment report + +### 6. Access Your Services + +**Immediately after deployment:** + +1. **Nextcloud**: `https://cloud.yourdomain.com` + - Login with admin credentials from setup + +2. **Setup Uptime Kuma** (via Tailscale): + - `https://uptime.yourdomain.com` + - Create admin account on first visit + - Add monitors for your services + +3. **Configure Homarr** (via Tailscale): + - `https://home.yourdomain.com` + - Add service tiles + - Customize dashboard + +4. **OnlyOffice Integration**: + - Nextcloud → Settings → Administration → Office + - Document Server: `https://office.yourdomain.com` + +--- + +## 🔧 Post-Deployment Tasks + +### Activate Tailscale (if not done automatically) + +```bash +ssh user@server +sudo tailscale up +``` + +### Test Backups + +```bash +make backup +``` + +Or on the server: +```bash +ssh user@server +/opt/nextcloud-stack/backup.sh +``` + +### Check Service Status + +```bash +make status +``` + +Or on the server: +```bash +ssh user@server +cd /opt/nextcloud-stack +docker compose ps +``` + +### View Logs + +```bash +make logs +``` + +Or on the server: +```bash +ssh user@server +cd /opt/nextcloud-stack +docker compose logs -f +``` + +--- + +## 🎓 Learning Ansible Commands + +### Useful Makefile Shortcuts + +```bash +make help # Show all commands +make ping # Test connectivity +make check # Run preflight checks only +make deploy # Full deployment +make deploy-dry # Test without making changes +make status # Show container status +make logs # View all logs +make backup # Run manual backup +make restart # Restart all containers +make edit-vault # Edit encrypted secrets +``` + +### Direct Ansible Commands + +```bash +# Run specific playbook +ansible-playbook playbooks/01-preflight-checks.yml --ask-vault-pass + +# Run on specific server +ansible-playbook playbooks/site.yml --limit server1 --ask-vault-pass + +# Dry run (no changes) +ansible-playbook playbooks/site.yml --ask-vault-pass --check + +# View inventory +ansible-inventory --list + +# Run ad-hoc command +ansible all -m shell -a "docker ps" --ask-vault-pass +``` + +--- + +## 🚨 Troubleshooting + +### DNS Not Configured + +**Symptom**: Let's Encrypt fails + +**Solution**: Ensure all DNS A records point to server IP +```bash +dig +short cloud.yourdomain.com +``` + +### LXC Container Issues + +**Symptom**: Docker won't start + +**Solution** (on LXC host): +```bash +lxc config set CONTAINER_NAME security.nesting true +lxc restart CONTAINER_NAME +``` + +### Port Already in Use + +**Symptom**: Caddy fails to start + +**Solution**: +```bash +sudo systemctl stop apache2 +sudo systemctl stop nginx +``` + +### Full troubleshooting guide: +See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) + +--- + +## 📚 Additional Documentation + +- [README.md](README.md) - Complete project overview +- [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - Common issues and solutions +- [BACKUP_RESTORE.md](BACKUP_RESTORE.md) - Backup and restore procedures +- [AGENTS.md](AGENTS.md) - Development guidelines + +--- + +## 🔒 Security Best Practices + +### After Deployment + +1. **Change default passwords** (if you used simple ones during testing) +2. **Enable 2FA** in Nextcloud +3. **Review firewall rules**: `sudo ufw status` +4. **Check fail2ban**: `sudo fail2ban-client status sshd` +5. **Verify SSL certificates**: Visit all your domains in browser +6. **Test backups**: Ensure they're working +7. **Setup monitoring alerts** in Uptime Kuma + +### Ongoing Maintenance + +- **Weekly**: Check Uptime Kuma for service health +- **Monthly**: Test backup restore +- **Quarterly**: Review security updates +- **Annually**: Rotate passwords + +--- + +## 🆘 Getting Help + +1. **Check logs:** + ```bash + docker compose logs [service-name] + ``` + +2. **Deployment report:** + ```bash + cat /opt/nextcloud-stack/DEPLOYMENT.txt + ``` + +3. **System status:** + ```bash + docker compose ps + sudo systemctl status docker + ``` + +--- + +## ✅ Success Checklist + +After deployment, verify: + +- [ ] All containers running: `docker compose ps` +- [ ] Nextcloud accessible via HTTPS +- [ ] SSL certificate valid (green padlock in browser) +- [ ] Can login to Nextcloud +- [ ] OnlyOffice integration working +- [ ] Uptime Kuma showing all services green +- [ ] Homarr dashboard accessible +- [ ] Backup script runs successfully +- [ ] Tailscale connected (if using) + +--- + +**You're all set! Enjoy your self-hosted Nextcloud stack! 🎉** + +For questions or issues, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md) + +**Last Updated:** 2026-02-16 diff --git a/ansible/Makefile b/ansible/Makefile new file mode 100644 index 0000000..bc08f49 --- /dev/null +++ b/ansible/Makefile @@ -0,0 +1,61 @@ +# Makefile for Nextcloud Stack Deployment +# Provides convenient shortcuts for common Ansible operations + +.PHONY: help setup ping check deploy deploy-stack deploy-dry update backup logs status restart rollback clean edit-vault rekey-vault + +help: ## Show this help message + @echo "Nextcloud Stack Deployment - Make Commands" + @echo "" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' + +setup: ## Run interactive setup script + @./setup.sh + +ping: ## Test connectivity to all servers + @ansible all -m ping --ask-vault-pass + +check: ## Run preflight checks only + @ansible-playbook playbooks/01-preflight-checks.yml --ask-vault-pass + +deploy: ## Full deployment (all playbooks) + @ansible-playbook playbooks/site.yml --ask-vault-pass + +deploy-stack: ## Deploy stack only (skip system setup) + @ansible-playbook playbooks/05-deploy-stack.yml --ask-vault-pass + +deploy-dry: ## Dry run (check mode) + @ansible-playbook playbooks/site.yml --ask-vault-pass --check + +update: ## Update Docker images (safe services only) + @ansible all -m shell -a "cd /opt/nextcloud-stack && docker compose pull && docker compose up -d" --ask-vault-pass + +backup: ## Run manual backup on all servers + @ansible all -m shell -a "/opt/nextcloud-stack/backup.sh" --ask-vault-pass + +logs: ## Tail logs from all containers + @ansible all -m shell -a "cd /opt/nextcloud-stack && docker compose logs -f --tail=100" --ask-vault-pass + +status: ## Show container status + @ansible all -m shell -a "cd /opt/nextcloud-stack && docker compose ps" --ask-vault-pass + +restart: ## Restart all containers + @ansible all -m shell -a "cd /opt/nextcloud-stack && docker compose restart" --ask-vault-pass + +rollback: ## Emergency rollback + @ansible-playbook playbooks/99-rollback.yml --ask-vault-pass + +clean: ## Remove generated inventory (keeps vault) + @rm -f inventory/hosts.yml inventory/group_vars/all/vars.yml + @echo "Cleaned generated files (vault.yml preserved)" + +edit-vault: ## Edit encrypted vault + @ansible-vault edit inventory/group_vars/all/vault.yml + +rekey-vault: ## Change vault password + @ansible-vault rekey inventory/group_vars/all/vault.yml + +inventory: ## Show inventory configuration + @ansible-inventory --list + +graph: ## Show inventory graph + @ansible-inventory --graph diff --git a/ansible/PROJECT_SUMMARY.md b/ansible/PROJECT_SUMMARY.md new file mode 100644 index 0000000..d1f7766 --- /dev/null +++ b/ansible/PROJECT_SUMMARY.md @@ -0,0 +1,560 @@ +# Nextcloud Stack - Ansible Deployment Project + +## 🎉 Project Complete! + +This Ansible automation project provides complete, one-command deployment of a self-hosted Nextcloud productivity stack to Ubuntu-based LXC/VPS servers. + +--- + +## 📦 What's Included + +### Core Files + +``` +ansible-nextcloud-deployment/ +├── setup.sh # ⭐ Interactive configuration wizard +├── Makefile # Convenient command shortcuts +├── ansible.cfg # Ansible configuration +├── .gitignore # Git ignore rules +│ +├── inventory/ # Generated by setup.sh +│ ├── hosts.yml # Server inventory (generated) +│ └── group_vars/all/ +│ ├── vars.yml # Public variables (generated) +│ └── vault.yml # Encrypted secrets (generated) +│ +├── playbooks/ # ⭐ Deployment playbooks +│ ├── site.yml # Main orchestrator +│ ├── 01-preflight-checks.yml # DNS, connectivity validation +│ ├── 02-system-setup.yml # Packages, firewall, security +│ ├── 03-docker-setup.yml # Docker CE installation +│ ├── 04-tailscale-setup.yml # VPN setup +│ ├── 05-deploy-stack.yml # Docker Compose deployment +│ ├── 06-configure-caddy.yml # Reverse proxy + SSL +│ ├── 07-setup-backups.yml # Backup automation +│ ├── 08-post-deployment.yml # Final verification +│ └── 99-rollback.yml # Emergency rollback +│ +├── roles/ # ⭐ Ansible roles +│ ├── nextcloud_stack/ +│ │ └── templates/ +│ │ ├── docker-compose.yml.j2 # Complete stack definition +│ │ └── env.j2 # Environment variables +│ └── caddy/ +│ └── templates/ +│ └── Caddyfile.j2 # Reverse proxy config +│ +└── docs/ # ⭐ Documentation + ├── README.md # Project overview + ├── DEPLOYMENT_GUIDE.md # Quick start guide + ├── TROUBLESHOOTING.md # Common issues & solutions + └── BACKUP_RESTORE.md # Backup procedures +``` + +### Stack Components (12 Services) + +**Public Services** (via HTTPS): +- Nextcloud (file sync & collaboration) +- OnlyOffice (document editor) +- Excalidraw (whiteboard) +- Obsidian (note-taking) + +**Infrastructure**: +- PostgreSQL 18 (database) +- Redis 7 (cache) +- Caddy (reverse proxy + automatic SSL) + +**Management** (Tailscale-only): +- Homarr (dashboard) +- Dockhand (container manager) +- Uptime Kuma (monitoring) + +**Automation**: +- Watchtower (auto-updates with safety exclusions) + +--- + +## 🚀 Quick Start + +### 1. Configure + +```bash +./setup.sh +``` + +Interactive wizard collects all configuration: +- Server details (IP, domain, SSH) +- User information +- Admin credentials +- Subdomain preferences +- Tailscale auth key (optional) +- Monitoring settings + +**Generates:** +- `inventory/hosts.yml` - Server inventory +- `inventory/group_vars/all/vars.yml` - Public config +- `inventory/group_vars/all/vault.yml` - Encrypted secrets + +### 2. Deploy + +```bash +make deploy +``` + +Or: +```bash +ansible-playbook playbooks/site.yml --ask-vault-pass +``` + +**Duration:** 30-45 minutes per server + +### 3. Access + +- Nextcloud: `https://cloud.yourdomain.com` +- Homarr: `https://home.yourdomain.com` (Tailscale) +- Uptime Kuma: `https://uptime.yourdomain.com` (Tailscale) + +--- + +## ✨ Key Features + +### 🔒 Security + +- **Firewall**: UFW configured (only SSH, HTTP, HTTPS, Tailscale open) +- **Fail2ban**: SSH brute-force protection (5 failures = 10 min ban) +- **Automatic Security Updates**: Unattended upgrades enabled +- **Secret Management**: Ansible Vault encryption for all credentials +- **Access Control**: Management UIs restricted to Tailscale network +- **SSL/TLS**: Automatic Let's Encrypt certificates via Caddy +- **Container Isolation**: Dedicated Docker network + +### 💾 Backups + +- **Daily**: PostgreSQL database dumps (3:00 AM) +- **Weekly**: Full volume backups (Sundays, 3:00 AM) +- **Retention**: 30 days +- **Location**: `/opt/nextcloud-stack/backups/` +- **Off-site Ready**: rclone pre-installed +- **Automated**: Cron jobs configured +- **Tested**: Documented restore procedures + +### 🔄 Updates + +**Automated (Watchtower)**: +- Caddy, Excalidraw, Obsidian, Homarr, Dockhand, Uptime Kuma + +**Monitor Only**: +- OnlyOffice (notifications, manual update) + +**Manual Required**: +- Nextcloud, PostgreSQL, Redis (too critical to auto-update) + +### 🌐 Multi-Server Support + +Deploy identical stacks to multiple servers: +- Each server gets unique domain +- Fully independent deployments +- Shared Tailscale network (optional) + +### 📊 Monitoring + +- **Uptime Kuma**: Service health monitoring +- **Email Alerts**: Configurable notifications +- **Status Page**: Optional public status page +- **Container Health**: Docker healthchecks +- **SSL Monitoring**: Certificate expiry tracking + +--- + +## 📚 Documentation + +| Document | Purpose | +|----------|---------| +| [README.md](README.md) | Complete project overview, features, usage | +| [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md) | Step-by-step deployment instructions | +| [TROUBLESHOOTING.md](TROUBLESHOOTING.md) | Common issues and solutions | +| [BACKUP_RESTORE.md](BACKUP_RESTORE.md) | Backup and restore procedures | +| [AGENTS.md](AGENTS.md) | Docker Compose & Ansible guidelines | + +--- + +## 🛠️ Makefile Commands + +```bash +make help # Show all commands +make setup # Run interactive setup +make ping # Test connectivity +make check # Run preflight checks +make deploy # Full deployment +make deploy-dry # Test run (no changes) +make status # Show container status +make logs # View all logs +make backup # Run manual backup +make restart # Restart all containers +make edit-vault # Edit encrypted secrets +make rekey-vault # Change vault password +``` + +--- + +## 🎯 Design Principles + +### 1. **User-Friendly** +- Interactive setup script (no manual configuration editing) +- Automatic SSL certificates +- Clear documentation +- Helpful error messages + +### 2. **Secure by Default** +- Minimal firewall rules +- Encrypted secrets (Ansible Vault) +- Tailscale-only admin interfaces +- Automatic security updates +- No hardcoded credentials + +### 3. **Production-Ready** +- Automated backups +- Monitoring included +- Health checks configured +- Documented restore procedures +- Emergency rollback playbook + +### 4. **Maintainable** +- Modular playbook structure +- Clear variable naming +- Comprehensive comments +- Role-based organization +- Git-friendly (.gitignore configured) + +### 5. **Safe Updates** +- Critical services excluded from auto-update +- Watchtower uses label-based control +- Manual update procedures documented +- Rollback capability included + +--- + +## 🔧 Deployment Flow + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 1. SETUP (./setup.sh) │ +│ • Collect server details, domains, credentials │ +│ • Generate encrypted inventory & variables │ +│ • Create Ansible Vault with secrets │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 2. PREFLIGHT CHECKS (01-preflight-checks.yml) │ +│ • Verify Ansible version, SSH connectivity │ +│ • Check disk space, ports availability │ +│ • Validate DNS records, detect LXC │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 3. SYSTEM SETUP (02-system-setup.yml) │ +│ • Update packages, install essentials │ +│ • Configure UFW firewall, fail2ban │ +│ • Enable automatic security updates │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 4. DOCKER SETUP (03-docker-setup.yml) │ +│ • Remove old Docker installations │ +│ • Install Docker CE + Compose v2 │ +│ • Configure Docker daemon │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 5. TAILSCALE SETUP (04-tailscale-setup.yml) │ +│ • Install Tailscale │ +│ • Activate if auth key provided │ +│ • Enable systemd service │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 6. DEPLOY STACK (05-deploy-stack.yml) │ +│ • Create directory structure │ +│ • Template docker-compose.yml, .env, configs │ +│ • Pull Docker images, start containers │ +│ • Wait for services healthy │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 7. CONFIGURE CADDY (06-configure-caddy.yml) │ +│ • Validate Caddyfile syntax │ +│ • Reload Caddy configuration │ +│ • Obtain Let's Encrypt SSL certificates │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 8. SETUP BACKUPS (07-setup-backups.yml) │ +│ • Create backup script │ +│ • Configure cron jobs (daily/weekly) │ +│ • Run test backup │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 9. POST-DEPLOYMENT (08-post-deployment.yml) │ +│ • Verify all containers running │ +│ • Install Nextcloud apps │ +│ • Configure background jobs │ +│ • Create deployment report │ +└─────────────────────────────────────────────────────────────┘ + ↓ + ✅ DEPLOYMENT COMPLETE! +``` + +--- + +## 🧩 Template Files + +### docker-compose.yml.j2 + +Complete Docker Compose stack with: +- All 12 services configured +- Health checks for critical services +- Proper dependencies (depends_on with conditions) +- Watchtower labels for update control +- Named volumes and networks +- Environment variables from .env + +**Location**: `roles/nextcloud_stack/templates/docker-compose.yml.j2` + +### Caddyfile.j2 + +Caddy reverse proxy configuration with: +- Automatic SSL for all domains +- Public services (Nextcloud, OnlyOffice, etc.) +- Tailscale-restricted services (Homarr, Dockhand, Uptime Kuma) +- Security headers +- Large file upload support (10GB) +- Optional public status page + +**Location**: `roles/caddy/templates/Caddyfile.j2` + +### env.j2 + +Environment variables template with: +- Database credentials +- Redis password +- Nextcloud admin credentials +- Application secrets (Homarr) +- Domain configuration +- Timezone settings + +**Location**: `roles/nextcloud_stack/templates/env.j2` + +--- + +## 🔐 Security Considerations + +### Secrets Management + +All sensitive data encrypted with Ansible Vault: +- Database passwords +- Admin credentials +- Application secrets +- Tailscale auth keys + +**Never committed in plain text!** + +### Network Security + +- **Public**: Only Nextcloud and productivity apps +- **Tailscale-only**: All management interfaces +- **Internal**: Database and Redis (no external access) + +### Firewall Rules (UFW) + +``` +22/tcp - SSH +80/tcp - HTTP (redirects to HTTPS) +443/tcp - HTTPS +443/udp - HTTP/3 (QUIC) +41641/udp - Tailscale +Default: DENY +``` + +### Update Strategy + +**Why not auto-update everything?** + +- **Nextcloud**: Database migrations may fail automatically +- **PostgreSQL**: Schema changes could break Nextcloud +- **Redis**: Unlikely issues, but excluded for consistency + +**Safe to auto-update:** +- Stateless applications (Excalidraw, Obsidian) +- Infrastructure (Caddy) +- Management tools (Homarr, Dockhand) + +--- + +## 📊 Resource Usage (Approximate) + +### Disk Space + +- Docker images: ~5GB +- Initial volumes: ~2GB +- Backups (30 days): ~50GB +- **Total recommended**: 100GB minimum + +### Memory + +- PostgreSQL: ~256MB +- Redis: ~256MB (configured limit) +- Nextcloud: ~512MB +- OnlyOffice: ~2GB +- Other services: ~1GB combined +- **Total**: 4-6GB RAM recommended + +### Network + +- **Inbound**: 80, 443 (HTTP/HTTPS), 41641 (Tailscale) +- **Outbound**: Internet access required for Let's Encrypt, Docker images, updates + +--- + +## 🎓 Next Steps + +### Immediate + +1. **Test the deployment** on a test server first +2. **Verify DNS** is configured correctly +3. **Run setup.sh** and answer questions carefully +4. **Deploy** with `make deploy` +5. **Access Nextcloud** and complete initial setup + +### After Deployment + +1. **Configure Uptime Kuma** monitoring +2. **Customize Homarr** dashboard +3. **Test backups** with `make backup` +4. **Enable 2FA** in Nextcloud +5. **Install additional Nextcloud apps** as needed + +### Ongoing + +1. **Monitor** service health in Uptime Kuma +2. **Review backups** monthly +3. **Test restore** procedures quarterly +4. **Update Nextcloud** when new versions release (manually) +5. **Check logs** for any issues + +--- + +## 💡 Tips & Best Practices + +### For LXC Containers + +**On LXC host, enable nested virtualization:** +```bash +lxc config set CONTAINER_NAME security.nesting true +lxc restart CONTAINER_NAME +``` + +### For Production Use + +1. Use strong passwords (not example passwords) +2. Enable Nextcloud 2FA +3. Configure off-site backups with rclone +4. Set up Uptime Kuma email alerts +5. Review logs regularly + +### For Multiple Servers + +Each server can have: +- Different domain +- Different subdomain preferences +- Same or different Tailscale network + +Just run `setup.sh` and add all servers when prompted. + +--- + +## 🐛 Known Limitations + +1. **Watchtower is archived** (December 2025) + - Still works, but no longer maintained + - Consider alternative update strategies long-term + +2. **OnlyOffice needs 2GB+ RAM** + - May be slow on low-memory servers + - Consider disabling if not needed + +3. **First-time deployment takes 30-45 min** + - Mostly Docker image downloads + - Subsequent deploys are faster + +4. **Let's Encrypt rate limits** + - 50 certs/week per domain + - Use staging server for testing + +--- + +## 📜 License + +MIT License - Use freely, modify as needed + +--- + +## 🙏 Acknowledgments + +Built with these amazing open-source projects: + +- **Nextcloud** - File sync and collaboration +- **Caddy** - Automatic HTTPS web server +- **Ansible** - IT automation +- **Docker** - Containerization +- **PostgreSQL** - Database +- **Tailscale** - Zero-config VPN +- **OnlyOffice**, **Excalidraw**, **Obsidian** - Productivity tools +- **Homarr**, **Dockhand**, **Uptime Kuma** - Management & monitoring + +--- + +## 📞 Support + +**Documentation:** +- [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md) - Getting started +- [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - Fix common issues +- [BACKUP_RESTORE.md](BACKUP_RESTORE.md) - Backup procedures + +**Project Files:** +All source code, playbooks, and templates included in this repository. + +--- + +## ✅ Checklist for New Users + +Before deploying: +- [ ] Read DEPLOYMENT_GUIDE.md +- [ ] Install Ansible 2.14+ on control machine +- [ ] Have Ubuntu 20.04+ server ready +- [ ] Configure DNS A records +- [ ] Test SSH access to server +- [ ] Have domain name ready +- [ ] Decide on subdomain preferences + +After deploying: +- [ ] Access Nextcloud web UI +- [ ] Complete Nextcloud setup wizard +- [ ] Setup Uptime Kuma monitoring +- [ ] Configure Homarr dashboard +- [ ] Test backup with `make backup` +- [ ] Enable Nextcloud 2FA +- [ ] Review deployment report +- [ ] Save Ansible Vault password securely + +--- + +**Project Status**: ✅ Complete and Ready for Use + +**Last Updated**: 2026-02-16 + +**Version**: 1.0 + +--- + +**Happy self-hosting! 🎉** diff --git a/ansible/README.md b/ansible/README.md new file mode 100644 index 0000000..fce42bf --- /dev/null +++ b/ansible/README.md @@ -0,0 +1,382 @@ +# Nextcloud Stack - Automated Deployment with Ansible + +Complete automation for deploying a self-hosted Nextcloud productivity stack on Ubuntu-based LXC/VPS servers. + +## Features + +- **12 Services**: Nextcloud, OnlyOffice, Excalidraw, Obsidian, Homarr, Dockhand, Uptime Kuma, PostgreSQL, Redis, Caddy, Watchtower +- **Automatic SSL**: Let's Encrypt certificates via Caddy +- **Secure Management**: Tailscale-only access for admin interfaces +- **Auto-updates**: Watchtower with safety exclusions for critical services +- **Automated Backups**: Daily database backups, weekly volume backups (30-day retention) +- **Monitoring**: Uptime Kuma with configurable alerts +- **Multi-server**: Deploy to multiple VPS servers with unique domains + +## Quick Start + +### Prerequisites + +1. **Control Machine** (your laptop): + - Ansible 2.14+ installed + - SSH access to target servers + +2. **Target Server(s)**: + - Ubuntu 20.04+ (LXC container or VPS) + - Root or sudo access + - Minimum 100GB disk space + - Ports 80, 443 available + +3. **DNS Configuration** (BEFORE deployment): + ``` + cloud.yourdomain.com → YOUR_SERVER_IP + office.yourdomain.com → YOUR_SERVER_IP + draw.yourdomain.com → YOUR_SERVER_IP + notes.yourdomain.com → YOUR_SERVER_IP + home.yourdomain.com → YOUR_SERVER_IP + manage.yourdomain.com → YOUR_SERVER_IP + uptime.yourdomain.com → YOUR_SERVER_IP + ``` + +### Installation + +1. **Clone this repository**: + ```bash + git clone + cd ansible-nextcloud-deployment + ``` + +2. **Run interactive setup**: + ```bash + ./setup.sh + ``` + + This will ask for: + - Server IP addresses and domains + - Your name and email + - Admin credentials + - Subdomain preferences + - Tailscale auth key (optional) + - Monitoring email + - Ansible Vault password + +3. **Deploy the stack**: + ```bash + make deploy + ``` + + Or manually: + ```bash + ansible-playbook playbooks/site.yml --ask-vault-pass + ``` + +4. **Access your services**: + - Nextcloud: `https://cloud.yourdomain.com` + - OnlyOffice: `https://office.yourdomain.com` + - Homarr (Tailscale only): `https://home.yourdomain.com` + - Uptime Kuma (Tailscale only): `https://uptime.yourdomain.com` + +## Project Structure + +``` +ansible-nextcloud-deployment/ +├── setup.sh # Interactive configuration script +├── Makefile # Convenient command shortcuts +├── ansible.cfg # Ansible configuration +├── inventory/ +│ ├── hosts.yml # Generated by setup.sh +│ └── group_vars/all/ +│ ├── vars.yml # Public variables +│ └── vault.yml # Encrypted secrets +├── playbooks/ +│ ├── site.yml # Main orchestrator +│ ├── 01-preflight-checks.yml # Pre-deployment validation +│ ├── 02-system-setup.yml # System packages & security +│ ├── 03-docker-setup.yml # Docker installation +│ ├── 04-tailscale-setup.yml # VPN setup +│ ├── 05-deploy-stack.yml # Docker Compose deployment +│ ├── 06-configure-caddy.yml # Reverse proxy configuration +│ ├── 07-setup-backups.yml # Backup automation +│ └── 08-post-deployment.yml # Final verification +└── roles/ + ├── nextcloud_stack/ + │ └── templates/ + │ ├── docker-compose.yml.j2 + │ └── env.j2 + └── caddy/ + └── templates/ + └── Caddyfile.j2 +``` + +## Makefile Commands + +```bash +make help # Show all commands +make setup # Run interactive setup +make ping # Test connectivity +make check # Run preflight checks +make deploy # Full deployment +make deploy-dry # Dry run (no changes) +make status # Show container status +make logs # View container logs +make backup # Run manual backup +make restart # Restart all containers +make edit-vault # Edit encrypted secrets +``` + +## Service Stack + +| Service | Purpose | Port | Access | Auto-Update | +|---------|---------|------|--------|-------------| +| Caddy | Reverse proxy + SSL | 80, 443 | Public | ✅ | +| Nextcloud | File sync & collaboration | Internal | Public (via Caddy) | ❌ Manual | +| PostgreSQL 18 | Database | Internal | Internal only | ❌ Manual | +| Redis 7 | Cache layer | Internal | Internal only | ❌ Manual | +| OnlyOffice | Document editor | Internal | Public (via Caddy) | 👁️ Monitor | +| Excalidraw | Whiteboard tool | Internal | Public (via Caddy) | ✅ | +| Obsidian | Note-taking | Internal | Public (via Caddy) | ✅ | +| Homarr | Dashboard | Internal | Tailscale only | ✅ | +| Dockhand | Container manager | 3003 | Tailscale only | ✅ | +| Uptime Kuma | Monitoring | Internal | Tailscale only | ✅ | +| Watchtower | Auto-updater | N/A | N/A | N/A | + +## Security Features + +- **Firewall**: UFW configured with minimal open ports +- **Fail2ban**: SSH brute-force protection +- **Automatic Updates**: Unattended security updates enabled +- **Secret Management**: Ansible Vault encryption for all credentials +- **Access Control**: Management UIs restricted to Tailscale network +- **SSL/TLS**: Automatic Let's Encrypt certificates +- **Container Isolation**: Dedicated Docker network + +## Backup System + +- **Daily**: PostgreSQL database dumps (3:00 AM) +- **Weekly**: Full volume backups (Sundays) +- **Retention**: 30 days +- **Location**: `/opt/nextcloud-stack/backups/` +- **rclone**: Pre-installed for future remote backups + +### Manual Backup + +```bash +ssh user@server +cd /opt/nextcloud-stack +./backup.sh +``` + +### Restore from Backup + +See [BACKUP_RESTORE.md](BACKUP_RESTORE.md) for detailed procedures. + +## Tailscale Setup + +If you didn't provide an auth key during setup: + +```bash +ssh user@server +sudo tailscale up +``` + +Then access management interfaces via Tailscale IP or MagicDNS. + +## Updating Services + +### Safe to Auto-Update (Watchtower handles) +- Caddy, Excalidraw, Obsidian, Homarr, Dockhand, Uptime Kuma + +### Monitor Only (notifications, no auto-update) +- OnlyOffice + +### Manual Update Required +- Nextcloud +- PostgreSQL +- Redis + +### Updating Nextcloud Manually + +```bash +ssh user@server +cd /opt/nextcloud-stack + +# 1. Backup +./backup.sh + +# 2. Enable maintenance mode +docker exec -u www-data next php occ maintenance:mode --on + +# 3. Update +docker compose pull next +docker compose up -d next + +# 4. Run database migrations +docker exec -u www-data next php occ upgrade + +# 5. Disable maintenance mode +docker exec -u www-data next php occ maintenance:mode --off +``` + +## Troubleshooting + +### DNS Not Configured +**Error**: Let's Encrypt fails to issue certificates + +**Solution**: Ensure all DNS A records point to your server IP. Check with: +```bash +dig +short cloud.yourdomain.com +``` + +### LXC Container Issues +**Error**: Docker fails to start + +**Solution**: On LXC host, enable nested virtualization: +```bash +lxc config set CONTAINER_NAME security.nesting true +lxc restart CONTAINER_NAME +``` + +### Port Already in Use +**Error**: Port 80 or 443 already bound + +**Solution**: Check what's using the ports: +```bash +sudo ss -tlnp | grep ':80\|:443' +sudo systemctl stop apache2 # or nginx +``` + +### Nextcloud Stuck in Maintenance Mode +```bash +docker exec -u www-data next php occ maintenance:mode --off +``` + +### View Logs +```bash +cd /opt/nextcloud-stack +docker compose logs -f [service-name] +``` + +## Post-Deployment Tasks + +1. **Login to Nextcloud**: + - URL: `https://cloud.yourdomain.com` + - Username: (set during setup) + - Password: (stored in vault) + +2. **Setup Uptime Kuma**: + - URL: `https://uptime.yourdomain.com` (via Tailscale) + - Create admin account on first visit + - Configure monitors for your services + +3. **Configure Homarr Dashboard**: + - URL: `https://home.yourdomain.com` (via Tailscale) + - Add service tiles + - Customize layout + +4. **Configure OnlyOffice in Nextcloud**: + - Nextcloud Settings → Administration → Office + - Document Editing Service: `https://office.yourdomain.com` + +5. **Test Backups**: + ```bash + make backup + ``` + +## File Locations on Server + +``` +/opt/nextcloud-stack/ +├── docker-compose.yml +├── .env +├── backup.sh +├── configs/ +│ ├── caddy/Caddyfile +│ └── nextcloud/ +├── data/ +│ ├── homarr/ +│ └── obsidian/ +└── backups/ + ├── database/ + └── volumes/ +``` + +## Environment Variables + +All secrets are stored in `inventory/group_vars/all/vault.yml` (encrypted). + +To edit: +```bash +make edit-vault +``` + +## Multiple Server Deployment + +The setup script supports multiple servers. Each can have its own domain: + +```bash +Server 1: 192.168.1.100 → cloud1.example.com +Server 2: 192.168.1.101 → cloud2.anotherdomain.net +Server 3: 192.168.1.102 → personal.mydomain.org +``` + +Deploy to all: +```bash +make deploy +``` + +Deploy to specific server: +```bash +ansible-playbook playbooks/site.yml --limit server_hostname --ask-vault-pass +``` + +## Maintenance + +### Check Container Status +```bash +make status +``` + +### Restart Services +```bash +make restart +``` + +### Update Images (safe services only) +```bash +make update +``` + +### View Logs +```bash +make logs +``` + +## Uninstallation + +```bash +ssh user@server +cd /opt/nextcloud-stack +docker compose down -v # WARNING: Deletes all data! +cd /opt +rm -rf nextcloud-stack +``` + +## Support + +- See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for common issues +- See [BACKUP_RESTORE.md](BACKUP_RESTORE.md) for backup procedures +- See [AGENTS.md](AGENTS.md) for development guidelines + +## License + +MIT + +## Acknowledgments + +- Nextcloud team +- Caddy web server +- Ansible community +- All open-source contributors + +--- + +**Built with ❤️ for self-hosting enthusiasts** diff --git a/ansible/START_HERE.md b/ansible/START_HERE.md new file mode 100644 index 0000000..bafc888 --- /dev/null +++ b/ansible/START_HERE.md @@ -0,0 +1,192 @@ +# 👋 Welcome to Nextcloud Stack Ansible Deployment! + +## 🚀 Quick Start (Choose Your Path) + +### 🏃 I Want to Deploy NOW +1. Read → [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md) (10 min read) +2. Run → `./setup.sh` (5-10 min) +3. Deploy → `make deploy` (30-45 min) + +### 📚 I Want to Learn More First +1. Read → [README.md](README.md) - Complete project overview +2. Read → [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md) - Design & architecture +3. Then → Follow Quick Start above + +### 🔧 I'm Having Issues +1. Check → [TROUBLESHOOTING.md](TROUBLESHOOTING.md) +2. Check logs → `make logs` +3. Review → [BACKUP_RESTORE.md](BACKUP_RESTORE.md) if you need to restore + +--- + +## 📖 Documentation Index + +| Document | Purpose | Read Time | +|----------|---------|-----------| +| **[DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md)** | Step-by-step deployment instructions | 10 min | +| **[README.md](README.md)** | Complete project overview & features | 15 min | +| **[PROJECT_SUMMARY.md](PROJECT_SUMMARY.md)** | Technical details & design | 10 min | +| **[TROUBLESHOOTING.md](TROUBLESHOOTING.md)** | Common issues & solutions | Reference | +| **[BACKUP_RESTORE.md](BACKUP_RESTORE.md)** | Backup & restore procedures | Reference | +| **[AGENTS.md](AGENTS.md)** | Docker & Ansible development guidelines | Reference | + +--- + +## ✅ Pre-Deployment Checklist + +Before you begin, ensure you have: + +- [ ] Ubuntu 20.04+ server (LXC or VPS) +- [ ] Root or sudo access to server +- [ ] Minimum 100GB disk space on server +- [ ] Ansible 2.14+ installed on your laptop/control machine +- [ ] Domain name with DNS control +- [ ] SSH access configured to server + +**Critical:** DNS A records must point to your server BEFORE deployment! + +--- + +## 🎯 What You'll Get + +After deployment, you'll have: + +### Public Services (HTTPS) +- **Nextcloud** - File sync & collaboration +- **OnlyOffice** - Document editor (Word, Excel, PowerPoint) +- **Excalidraw** - Whiteboard & diagrams +- **Obsidian** - Note-taking & knowledge management + +### Management Tools (Tailscale-only, secure) +- **Homarr** - Beautiful dashboard for all services +- **Dockhand** - Container management interface +- **Uptime Kuma** - Monitoring & alerts + +### Infrastructure (automatic, invisible) +- **Caddy** - Reverse proxy with automatic SSL +- **PostgreSQL** - Database +- **Redis** - Cache for better performance +- **Watchtower** - Automatic updates (safe services only) + +--- + +## 💡 Key Features + +- ✅ **One-command deployment** - `make deploy` does everything +- ✅ **Automatic SSL** - Let's Encrypt certificates via Caddy +- ✅ **Secure by default** - Firewall, fail2ban, Vault encryption +- ✅ **Auto backups** - Daily DB, weekly volumes (30-day retention) +- ✅ **Multi-server** - Deploy to multiple VPS with unique domains +- ✅ **Production-ready** - Monitoring, backups, documentation + +--- + +## 🏗️ Project Structure + +``` +/home/liph/programming/ansible/ +├── setup.sh ⭐ # Start here! Interactive setup +├── Makefile # Convenient commands (make deploy) +├── playbooks/ # 10 Ansible playbooks +│ ├── site.yml # Main orchestrator +│ ├── 01-preflight-checks.yml # Validates environment +│ ├── 02-system-setup.yml # Packages & security +│ ├── 03-docker-setup.yml # Docker installation +│ ├── 04-tailscale-setup.yml # VPN setup +│ ├── 05-deploy-stack.yml # Main deployment +│ ├── 06-configure-caddy.yml # SSL & reverse proxy +│ ├── 07-setup-backups.yml # Backup automation +│ ├── 08-post-deployment.yml # Verification +│ └── 99-rollback.yml # Emergency rollback +├── roles/ # Templates & configs +│ ├── nextcloud_stack/ +│ │ └── templates/ +│ │ ├── docker-compose.yml.j2 # 12-service stack +│ │ └── env.j2 # Environment vars +│ └── caddy/ +│ └── templates/ +│ └── Caddyfile.j2 # Reverse proxy config +└── docs/ # You are here! +``` + +--- + +## 🎓 Common Commands + +After setup, you'll use these frequently: + +```bash +make deploy # Deploy everything +make status # Check container status +make logs # View all logs +make backup # Run manual backup +make restart # Restart all containers +make edit-vault # Edit encrypted secrets +``` + +--- + +## 📞 Need Help? + +1. **Common Issues**: [TROUBLESHOOTING.md](TROUBLESHOOTING.md) +2. **Backup/Restore**: [BACKUP_RESTORE.md](BACKUP_RESTORE.md) +3. **Full Documentation**: [README.md](README.md) + +--- + +## ⚡ 30-Second Overview + +This project automates deploying a complete self-hosted productivity stack: + +1. **Configure once**: `./setup.sh` collects all info +2. **Deploy anywhere**: `make deploy` to any Ubuntu server +3. **Use immediately**: Access via `https://cloud.yourdomain.com` + +**Time to deploy:** 30-45 minutes (mostly automatic) + +--- + +## 🎯 Recommended First Steps + +### For Complete Beginners +1. Read [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md) +2. Configure DNS for your domain +3. Run `./setup.sh` on your laptop +4. Run `make deploy` and wait +5. Access your new Nextcloud! + +### For Experienced Users +1. Skim [README.md](README.md) to understand the stack +2. Review [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md) for architecture +3. Run `./setup.sh` and `make deploy` +4. Review generated configs in `/opt/nextcloud-stack/` + +### For Developers +1. Read [AGENTS.md](AGENTS.md) for development guidelines +2. Review playbooks in `playbooks/` directory +3. Check templates in `roles/*/templates/` +4. Customize as needed for your use case + +--- + +## 🌟 What Makes This Special? + +- **User-friendly**: Interactive setup, no manual config editing +- **Secure**: Ansible Vault, firewalls, Tailscale, automatic updates +- **Complete**: Monitoring, backups, SSL, documentation included +- **Production-ready**: Tested deployment procedures, rollback capability +- **Maintainable**: Clean code, comprehensive docs, modular design + +--- + +## 🚦 Ready to Begin? + +**New users**: Start with [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md) + +**Quick reference**: See [README.md](README.md) + +**Technical details**: Check [PROJECT_SUMMARY.md](PROJECT_SUMMARY.md) + +--- + +**Let's build your self-hosted cloud! 🚀** diff --git a/ansible/TROUBLESHOOTING.md b/ansible/TROUBLESHOOTING.md new file mode 100644 index 0000000..1ef1fff --- /dev/null +++ b/ansible/TROUBLESHOOTING.md @@ -0,0 +1,509 @@ +# Troubleshooting Guide + +Common issues and solutions for Nextcloud Stack deployment. + +## Table of Contents + +- [DNS Issues](#dns-issues) +- [SSL Certificate Problems](#ssl-certificate-problems) +- [Docker Issues](#docker-issues) +- [LXC Container Issues](#lxc-container-issues) +- [Nextcloud Issues](#nextcloud-issues) +- [Database Connection Issues](#database-connection-issues) +- [Tailscale Issues](#tailscale-issues) +- [Port Conflicts](#port-conflicts) +- [Permission Issues](#permission-issues) + +--- + +## DNS Issues + +### Problem: DNS records not resolving + +**Symptoms:** +- Let's Encrypt fails to issue certificates +- Caddy shows certificate errors +- Services inaccessible via domain + +**Diagnosis:** +```bash +dig +short cloud.yourdomain.com @8.8.8.8 +``` + +**Solution:** +1. Ensure all required A records point to your server IP +2. Wait for DNS propagation (up to 48 hours, usually minutes) +3. Use [DNSChecker.org](https://dnschecker.org) to verify global propagation + +**Required DNS Records:** +``` +cloud.yourdomain.com → YOUR_SERVER_IP +office.yourdomain.com → YOUR_SERVER_IP +draw.yourdomain.com → YOUR_SERVER_IP +notes.yourdomain.com → YOUR_SERVER_IP +home.yourdomain.com → YOUR_SERVER_IP +manage.yourdomain.com → YOUR_SERVER_IP +uptime.yourdomain.com → YOUR_SERVER_IP +``` + +**Temporary Workaround:** +Edit `/etc/hosts` on your local machine: +``` +YOUR_SERVER_IP cloud.yourdomain.com +``` + +--- + +## SSL Certificate Problems + +### Problem: Let's Encrypt rate limit exceeded + +**Symptoms:** +- Error: "too many certificates already issued" + +**Solution:** +1. Use Let's Encrypt staging server for testing +2. Edit Caddyfile (add to global options): + ```caddy + { + email {{ user_email }} + acme_ca https://acme-staging-v02.api.letsencrypt.org/directory + } + ``` +3. Reload Caddy: `docker exec caddy caddy reload` +4. After testing, remove staging server line + +**Rate Limits:** +- 50 certificates per domain per week +- 5 duplicate certificates per week + +### Problem: Certificate validation failed + +**Symptoms:** +- "Failed to verify" errors in Caddy logs + +**Diagnosis:** +```bash +docker logs caddy +``` + +**Common Causes:** +1. DNS not pointing to server +2. Firewall blocking port 80/443 +3. Another service using port 80/443 + +**Solution:** +```bash +# Check firewall +sudo ufw status + +# Check port usage +sudo ss -tlnp | grep ':80\|:443' + +# Check DNS +dig +short yourdomain.com +``` + +--- + +## Docker Issues + +### Problem: Docker daemon won't start + +**Symptoms:** +- `docker ps` fails +- Error: "Cannot connect to Docker daemon" + +**Diagnosis:** +```bash +sudo systemctl status docker +sudo journalctl -xu docker +``` + +**Solution:** +```bash +sudo systemctl restart docker +``` + +### Problem: Containers keep restarting + +**Diagnosis:** +```bash +cd /opt/nextcloud-stack +docker compose logs [service-name] +``` + +**Common Causes:** +1. Configuration errors +2. Port conflicts +3. Missing dependencies + +**Solution:** +```bash +# Check specific container +docker logs next-db +docker logs next +docker logs caddy + +# Restart specific service +docker compose restart next +``` + +--- + +## LXC Container Issues + +### Problem: Docker fails to start in LXC + +**Symptoms:** +- Error: "cgroups: cgroup mountpoint does not exist" +- Docker daemon fails to start + +**Diagnosis:** +```bash +systemd-detect-virt # Should show "lxc" +``` + +**Solution on LXC Host:** +```bash +# Set security nesting +lxc config set CONTAINER_NAME security.nesting true + +# May also need privileged mode +lxc config set CONTAINER_NAME security.privileged true + +# Restart container +lxc restart CONTAINER_NAME +``` + +**Inside LXC Container:** +```bash +# Verify cgroups +mount | grep cgroup + +# Check Docker status +sudo systemctl status docker +``` + +### Problem: AppArmor denials in LXC + +**Solution on LXC Host:** +```bash +lxc config set CONTAINER_NAME raw.lxc "lxc.apparmor.profile=unconfined" +lxc restart CONTAINER_NAME +``` + +--- + +## Nextcloud Issues + +### Problem: Nextcloud stuck in maintenance mode + +**Symptoms:** +- Web interface shows "System in maintenance mode" + +**Solution:** +```bash +docker exec -u www-data next php occ maintenance:mode --off +``` + +### Problem: Trusted domain error + +**Symptoms:** +- "Access through untrusted domain" error + +**Solution:** +```bash +docker exec -u www-data next php occ config:system:set trusted_domains 1 --value=cloud.yourdomain.com +``` + +### Problem: Redis connection failed + +**Diagnosis:** +```bash +docker logs next-redis +docker exec next-redis redis-cli ping +``` + +**Solution:** +```bash +# Reconfigure Redis in Nextcloud +docker exec -u www-data next php occ config:system:set redis host --value=next-redis +docker exec -u www-data next php occ config:system:set redis port --value=6379 +``` + +### Problem: File uploads fail + +**Symptoms:** +- Large files won't upload +- Error 413 (Payload Too Large) + +**Solution:** +Already configured in Caddyfile for 10GB uploads. Check: +```bash +docker exec -u www-data next php occ config:system:get max_upload +``` + +### Problem: OnlyOffice integration not working + +**Solution:** +```bash +# Install OnlyOffice app +docker exec -u www-data next php occ app:install onlyoffice + +# Configure document server URL +docker exec -u www-data next php occ config:app:set onlyoffice DocumentServerUrl --value="https://office.yourdomain.com/" + +# Disable JWT (or configure if needed) +docker exec -u www-data next php occ config:app:set onlyoffice jwt_secret --value="" +``` + +--- + +## Database Connection Issues + +### Problem: Nextcloud can't connect to database + +**Symptoms:** +- Error: "SQLSTATE[08006]" +- Nextcloud shows database error + +**Diagnosis:** +```bash +# Check if PostgreSQL is running +docker ps | grep next-db + +# Check PostgreSQL logs +docker logs next-db + +# Test connection +docker exec next-db pg_isready -U nextcloud +``` + +**Solution:** +```bash +# Restart database +docker compose restart next-db + +# Wait for it to be healthy +docker exec next-db pg_isready -U nextcloud + +# Restart Nextcloud +docker compose restart next +``` + +### Problem: Database initialization failed + +**Symptoms:** +- PostgreSQL container keeps restarting +- Empty database + +**Solution:** +```bash +# Remove volumes and recreate +cd /opt/nextcloud-stack +docker compose down -v +docker compose up -d +``` + +**⚠️ WARNING:** This deletes all data! Only use for fresh installations. + +--- + +## Tailscale Issues + +### Problem: Can't access Tailscale-only services + +**Symptoms:** +- Homarr, Dockhand, Uptime Kuma return 403 Forbidden + +**Diagnosis:** +```bash +# Check if Tailscale is running +sudo tailscale status + +# Get Tailscale IP +tailscale ip -4 +``` + +**Solution:** +```bash +# Activate Tailscale (if not done) +sudo tailscale up + +# Verify connection +tailscale status +``` + +**Access via:** +- Tailscale IP: `https://100.64.x.x:PORT` +- MagicDNS: `https://hostname.tailnet-name.ts.net` + +### Problem: Tailscale not installed + +**Solution:** +```bash +# Re-run Tailscale playbook +ansible-playbook playbooks/04-tailscale-setup.yml --ask-vault-pass +``` + +--- + +## Port Conflicts + +### Problem: Port 80 or 443 already in use + +**Symptoms:** +- Error: "bind: address already in use" +- Caddy won't start + +**Diagnosis:** +```bash +sudo ss -tlnp | grep ':80\|:443' +``` + +**Common Culprits:** +- Apache2 +- Nginx +- Another Caddy instance + +**Solution:** +```bash +# Stop conflicting service +sudo systemctl stop apache2 +sudo systemctl disable apache2 + +# OR +sudo systemctl stop nginx +sudo systemctl disable nginx + +# Restart Caddy +docker compose restart caddy +``` + +--- + +## Permission Issues + +### Problem: Permission denied errors in Nextcloud + +**Symptoms:** +- Can't upload files +- Can't install apps + +**Diagnosis:** +```bash +# Check file permissions +docker exec next ls -la /var/www/html +``` + +**Solution:** +```bash +# Fix permissions (run inside container) +docker exec next chown -R www-data:www-data /var/www/html +``` + +### Problem: Docker socket permission denied + +**Symptoms:** +- Homarr or Dockhand can't see containers + +**Solution:** +Docker socket is mounted read-only by design for security. +This is normal and expected. + +--- + +## Emergency Commands + +### Completely restart the stack +```bash +cd /opt/nextcloud-stack +docker compose down +docker compose up -d +``` + +### View all logs in real-time +```bash +cd /opt/nextcloud-stack +docker compose logs -f +``` + +### Check container health +```bash +docker compose ps +docker inspect --format='{{.State.Health.Status}}' next +``` + +### Rebuild a specific container +```bash +docker compose up -d --force-recreate --no-deps next +``` + +### Emergency backup +```bash +/opt/nextcloud-stack/backup.sh +``` + +### Reset Nextcloud admin password +```bash +docker exec -u www-data next php occ user:resetpassword admin +``` + +--- + +## Getting Help + +If none of these solutions work: + +1. **Check logs:** + ```bash + docker compose logs [service-name] + ``` + +2. **Check system logs:** + ```bash + sudo journalctl -xe + ``` + +3. **Verify configuration:** + ```bash + cat /opt/nextcloud-stack/docker-compose.yml + cat /opt/nextcloud-stack/.env + ``` + +4. **Test connectivity:** + ```bash + curl -I https://cloud.yourdomain.com + docker exec caddy caddy validate + ``` + +5. **Deployment report:** + ```bash + cat /opt/nextcloud-stack/DEPLOYMENT.txt + ``` + +--- + +## Recovery Procedures + +### Restore from backup + +See [BACKUP_RESTORE.md](BACKUP_RESTORE.md) + +### Complete reinstallation + +```bash +# 1. Backup first! +/opt/nextcloud-stack/backup.sh + +# 2. Remove deployment +ansible-playbook playbooks/99-rollback.yml --ask-vault-pass + +# 3. Redeploy +ansible-playbook playbooks/site.yml --ask-vault-pass +``` + +--- + +**Last Updated:** 2026-02-16 diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg new file mode 100644 index 0000000..b3564ce --- /dev/null +++ b/ansible/ansible.cfg @@ -0,0 +1,35 @@ +# Ansible Configuration File +# Generated for Nextcloud Stack Deployment + +[defaults] +inventory = inventory/hosts.yml +roles_path = roles +host_key_checking = False +retry_files_enabled = False +gathering = smart +fact_caching = jsonfile +fact_caching_connection = /tmp/ansible_facts +fact_caching_timeout = 3600 +stdout_callback = yaml +callbacks_enabled = profile_tasks, timer +deprecation_warnings = False + +# SSH settings +timeout = 30 +forks = 5 + +# Privilege escalation +become = True +become_method = sudo +become_ask_pass = False + +[privilege_escalation] +become = True +become_method = sudo +become_user = root +become_ask_pass = False + +[ssh_connection] +ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no +pipelining = True +control_path = /tmp/ansible-ssh-%%h-%%p-%%r diff --git a/ansible/nextcloud/.env b/ansible/nextcloud/.env new file mode 100755 index 0000000..1651aaf --- /dev/null +++ b/ansible/nextcloud/.env @@ -0,0 +1,7 @@ +DB_PASSWORD= +DB_USERNAME= +DB_DATABASE_NAME= +DB_HOST= + +PUID=33 +PGID=1000 diff --git a/ansible/nextcloud/docker-compose.yml b/ansible/nextcloud/docker-compose.yml new file mode 100755 index 0000000..5e0454c --- /dev/null +++ b/ansible/nextcloud/docker-compose.yml @@ -0,0 +1,108 @@ +services: + excalidraw: + container_name: excalidraw + image: docker.io/excalidraw/excalidraw:latest + restart: unless-stopped + ports: + - "3009:80" + environment: + - NODE_ENV=production + - TZ=Europe/Zurich + + # Database (PostgreSQL) + next-db: + image: docker.io/postgres:18 + container_name: next-db + environment: + - POSTGRES_DB=${DB_DATABASE_NAME} + - POSTGRES_USER=${DB_USERNAME} + - POSTGRES_PASSWORD=${DB_PASSWORD} + volumes: + - + restart: unless-stopped + networks: + - nextcloud_network + + # # Redis Cache + # next_redis: + # image: docker.io/redis:latest + # container_name: next-redis + # command: redis-server --save 60 1 --loglevel warning + # volumes: + # - ./data/redis:/data + # restart: unless-stopped + # networks: + # - nextcloud_network + + # Nextcloud Main Application + next: + image: docker.io/nextcloud:latest + container_name: next + depends_on: + - next-db + mem_swappiness: -1 + ports: + - "8808:80" + environment: + - POSTGRES_DB=${DB_DATABASE_NAME} + - POSTGRES_USER=${DB_USERNAME} + - POSTGRES_PASSWORD=${DB_PASSWORD} + - POSTGRES_HOST=${DB_HOST} + - NEXTCLOUD_TRUSTED_DOMAINS=next.liphlink.xyz + - NEXTCLOUD_ADMIN_USER=liph + - NEXTCLOUD_ADMIN_PASSWORD=1ChagenexT + volumes: + - :/var/www/html + - :/var/www/html/config:Z + - :/var/www/html/custom_apps + restart: unless-stopped + networks: + - nextcloud_network + + # OnlyOffice (alternative to Collabora) + onlyoffice: + image: docker.io/onlyoffice/documentserver:latest + container_name: onlyoffice + ports: + - 8000:80 + environment: + # - JWT_SECRET='S2jaRmOxSxnFoOMhzXotL1QTptDuqhom' + - JWT_ENABLED=false + - JWT_HEADER=Authorization + - JWT_IN_BODY=true + volumes: + - :/var/www/onlyoffice/Data + restart: unless-stopped + networks: + - nextcloud_network + + obsidian: + image: lscr.io/linuxserver/obsidian:latest + container_name: obsidian + security_opt: + - seccomp:unconfined #optional + environment: + - PUID=1000 + - PGID=1000 + - TZ=Etc/UTC + volumes: + - :/config:z + - :/vault:z + ports: + - 3005:3000 + - 3004:3001 + shm_size: "1gb" + restart: unless-stopped + +volumes: + pg_data: + redis_data: + nextcloud_data: + nextcloud_config: + nextcloud_apps: + nextcloud_db_data: + onlyoffice_data: + +networks: + nextcloud_network: + name: nextcloud_network diff --git a/ansible/playbooks/01-preflight-checks.yml b/ansible/playbooks/01-preflight-checks.yml new file mode 100644 index 0000000..2d363af --- /dev/null +++ b/ansible/playbooks/01-preflight-checks.yml @@ -0,0 +1,98 @@ +--- +# Playbook 01: Preflight Checks +# Validates environment before deployment + +- name: Preflight Checks + hosts: all + gather_facts: yes + become: no + + tasks: + - name: Check Ansible version + assert: + that: + - ansible_version.full is version('2.14', '>=') + fail_msg: "Ansible 2.14 or higher is required" + success_msg: "Ansible version OK ({{ ansible_version.full }})" + delegate_to: localhost + run_once: true + + - name: Test SSH connectivity + ping: + + - name: Check sudo access + command: sudo -n true + changed_when: false + + - name: Check Python3 availability + command: python3 --version + register: python_version + changed_when: false + + - name: Display Python version + debug: + msg: "Python version: {{ python_version.stdout }}" + + - name: Check disk space + shell: df -h / | awk 'NR==2 {print $4}' + register: disk_space + changed_when: false + + - name: Validate sufficient disk space + assert: + that: + - disk_space.stdout is regex('[0-9]+G') + fail_msg: "Insufficient disk space. At least 20GB recommended." + success_msg: "Disk space OK ({{ disk_space.stdout }} available)" + + - name: Check if ports 80 and 443 are available + wait_for: + port: "{{ item }}" + state: stopped + timeout: 1 + loop: + - 80 + - 443 + ignore_errors: yes + register: port_check + + - name: Detect virtualization type + command: systemd-detect-virt + register: virt_type + changed_when: false + failed_when: false + + - name: Warn if running in LXC + debug: + msg: | + ⚠️ RUNNING IN LXC CONTAINER + Docker requires nested virtualization. + Ensure on LXC host: lxc config set {{ inventory_hostname }} security.nesting true + when: "'lxc' in virt_type.stdout" + + - name: Validate DNS resolution for all subdomains + command: dig +short {{ item }}.{{ domain }} @8.8.8.8 + register: dns_check + changed_when: false + failed_when: false + loop: + - "{{ subdomain_nextcloud }}" + - "{{ subdomain_office }}" + - "{{ subdomain_draw }}" + - "{{ subdomain_notes }}" + - "{{ subdomain_homarr }}" + - "{{ subdomain_dockhand }}" + - "{{ subdomain_uptime }}" + + - name: Display DNS check results + debug: + msg: "{{ item.item }}.{{ domain }} → {{ item.stdout if item.stdout else 'NOT CONFIGURED' }}" + loop: "{{ dns_check.results }}" + loop_control: + label: "{{ item.item }}.{{ domain }}" + + - name: Preflight checks complete + debug: + msg: | + ✓ All preflight checks passed + ✓ Ready to proceed with deployment diff --git a/ansible/playbooks/02-system-setup.yml b/ansible/playbooks/02-system-setup.yml new file mode 100644 index 0000000..91db736 --- /dev/null +++ b/ansible/playbooks/02-system-setup.yml @@ -0,0 +1,119 @@ +--- +# Playbook 02: System Setup +# Install packages, configure firewall and security + +- name: System Setup + hosts: all + become: yes + + tasks: + - name: Update apt cache + apt: + update_cache: yes + cache_valid_time: 3600 + + - name: Upgrade all packages + apt: + upgrade: dist + autoremove: yes + autoclean: yes + + - name: Install essential packages + apt: + name: + - curl + - wget + - git + - vim + - htop + - net-tools + - dnsutils + - ufw + - fail2ban + - unattended-upgrades + - apt-transport-https + - ca-certificates + - gnupg + - lsb-release + - software-properties-common + - python3-pip + - python3-docker + - rsync + - "{% if install_rclone %}rclone{% endif %}" + state: present + + - name: Configure UFW - Allow SSH + ufw: + rule: allow + port: '22' + proto: tcp + + - name: Configure UFW - Allow HTTP + ufw: + rule: allow + port: '80' + proto: tcp + + - name: Configure UFW - Allow HTTPS TCP + ufw: + rule: allow + port: '443' + proto: tcp + + - name: Configure UFW - Allow HTTPS UDP (HTTP/3) + ufw: + rule: allow + port: '443' + proto: udp + + - name: Configure UFW - Allow Tailscale + ufw: + rule: allow + port: '41641' + proto: udp + + - name: Enable UFW + ufw: + state: enabled + policy: deny + + - name: Configure fail2ban for SSH + copy: + dest: /etc/fail2ban/jail.local + content: | + [sshd] + enabled = true + port = ssh + filter = sshd + logpath = /var/log/auth.log + maxretry = 5 + bantime = 600 + notify: restart fail2ban + + - name: Enable unattended security updates + copy: + dest: /etc/apt/apt.conf.d/20auto-upgrades + content: | + APT::Periodic::Update-Package-Lists "1"; + APT::Periodic::Unattended-Upgrade "1"; + APT::Periodic::AutocleanInterval "7"; + + - name: Set timezone + timezone: + name: "{{ timezone }}" + + - name: Set kernel parameters for Docker + sysctl: + name: "{{ item.key }}" + value: "{{ item.value }}" + state: present + reload: yes + loop: + - { key: 'net.ipv4.ip_forward', value: '1' } + - { key: 'fs.inotify.max_user_watches', value: '524288' } + + handlers: + - name: restart fail2ban + service: + name: fail2ban + state: restarted diff --git a/ansible/playbooks/03-docker-setup.yml b/ansible/playbooks/03-docker-setup.yml new file mode 100644 index 0000000..5cc5c99 --- /dev/null +++ b/ansible/playbooks/03-docker-setup.yml @@ -0,0 +1,115 @@ +--- +# Playbook 03: Docker Setup +# Install Docker CE and Docker Compose v2 + +- name: Docker Installation + hosts: all + become: yes + + tasks: + - name: Remove old Docker installations + apt: + name: + - docker + - docker-engine + - docker.io + - containerd + - runc + - docker-compose + state: absent + purge: yes + + - name: Remove old Docker data directories + file: + path: "{{ item }}" + state: absent + loop: + - /var/lib/docker + - /var/lib/containerd + - /etc/docker + + - name: Add Docker GPG key + apt_key: + url: https://download.docker.com/linux/ubuntu/gpg + state: present + + - name: Add Docker repository + apt_repository: + repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" + state: present + + - name: Install Docker CE + apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + - docker-compose-plugin + state: present + update_cache: yes + + - name: Create Docker daemon configuration + copy: + dest: /etc/docker/daemon.json + content: | + { + "log-driver": "json-file", + "log-opts": { + "max-size": "10m", + "max-file": "3" + }, + "storage-driver": "overlay2", + "userland-proxy": false, + "live-restore": true + } + notify: restart docker + + - name: Create docker group + group: + name: docker + state: present + + - name: Add user to docker group + user: + name: "{{ ansible_user }}" + groups: docker + append: yes + + - name: Create deployment directory + file: + path: "{{ deployment_dir }}" + state: directory + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: '0755' + + - name: Start and enable Docker + service: + name: docker + state: started + enabled: yes + + - name: Verify Docker installation + command: docker --version + register: docker_version + changed_when: false + + - name: Display Docker version + debug: + msg: "Docker installed: {{ docker_version.stdout }}" + + - name: Verify Docker Compose installation + command: docker compose version + register: compose_version + changed_when: false + + - name: Display Docker Compose version + debug: + msg: "Docker Compose installed: {{ compose_version.stdout }}" + + handlers: + - name: restart docker + service: + name: docker + state: restarted diff --git a/ansible/playbooks/04-tailscale-setup.yml b/ansible/playbooks/04-tailscale-setup.yml new file mode 100644 index 0000000..355e8de --- /dev/null +++ b/ansible/playbooks/04-tailscale-setup.yml @@ -0,0 +1,60 @@ +--- +# Playbook 04: Tailscale Setup +# Install and optionally activate Tailscale VPN + +- name: Tailscale Installation + hosts: all + become: yes + + tasks: + - name: Add Tailscale GPG key + apt_key: + url: https://pkgs.tailscale.com/stable/ubuntu/{{ ansible_distribution_release }}.noarmor.gpg + state: present + + - name: Add Tailscale repository + apt_repository: + repo: "deb https://pkgs.tailscale.com/stable/ubuntu {{ ansible_distribution_release }} main" + state: present + + - name: Install Tailscale + apt: + name: tailscale + state: present + update_cache: yes + + - name: Check if Tailscale auth key is provided + set_fact: + tailscale_auto_enable: "{{ tailscale_auth_key is defined and tailscale_auth_key != '' }}" + + - name: Activate Tailscale (if auth key provided) + command: tailscale up --authkey={{ tailscale_auth_key }} --advertise-tags=tag:nextcloud + when: tailscale_auto_enable + register: tailscale_activation + + - name: Get Tailscale IP (if activated) + command: tailscale ip -4 + register: tailscale_ip + when: tailscale_auto_enable + changed_when: false + + - name: Display Tailscale status (activated) + debug: + msg: | + ✓ Tailscale activated + IP: {{ tailscale_ip.stdout }} + when: tailscale_auto_enable + + - name: Display manual activation instructions (not activated) + debug: + msg: | + Tailscale installed but not activated. + To enable, run on the server: + sudo tailscale up + when: not tailscale_auto_enable + + - name: Enable Tailscale service + service: + name: tailscaled + state: started + enabled: yes diff --git a/ansible/playbooks/05-deploy-stack.yml b/ansible/playbooks/05-deploy-stack.yml new file mode 100644 index 0000000..d950c49 --- /dev/null +++ b/ansible/playbooks/05-deploy-stack.yml @@ -0,0 +1,109 @@ +--- +# Playbook 05: Deploy Stack +# Deploy Docker Compose stack with all services + +- name: Deploy Nextcloud Stack + hosts: all + become: yes + + tasks: + - name: Create directory structure + file: + path: "{{ item }}" + state: directory + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: '0755' + loop: + - "{{ deployment_dir }}/configs" + - "{{ deployment_dir }}/configs/caddy" + - "{{ deployment_dir }}/configs/nextcloud" + - "{{ deployment_dir }}/data" + - "{{ deployment_dir }}/data/homarr" + - "{{ deployment_dir }}/data/obsidian/config" + - "{{ deployment_dir }}/data/obsidian/vault" + - "{{ deployment_dir }}/backups" + - "{{ deployment_dir }}/backups/database" + - "{{ deployment_dir }}/backups/volumes" + + - name: Template docker-compose.yml + template: + src: ../roles/nextcloud_stack/templates/docker-compose.yml.j2 + dest: "{{ deployment_dir }}/docker-compose.yml" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: '0644' + + - name: Template .env file + template: + src: ../roles/nextcloud_stack/templates/env.j2 + dest: "{{ deployment_dir }}/.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: '0600' + no_log: true + + - name: Template Caddyfile + template: + src: ../roles/caddy/templates/Caddyfile.j2 + dest: "{{ deployment_dir }}/configs/caddy/Caddyfile" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: '0644' + + - name: Pull Docker images + command: docker compose pull + args: + chdir: "{{ deployment_dir }}" + become_user: "{{ ansible_user }}" + + - name: Start Docker Compose stack + command: docker compose up -d + args: + chdir: "{{ deployment_dir }}" + become_user: "{{ ansible_user }}" + + - name: Wait for PostgreSQL to be healthy + command: docker exec next-db pg_isready -U {{ db_user }} + register: pg_ready + until: pg_ready.rc == 0 + retries: 30 + delay: 10 + changed_when: false + + - name: Wait for Nextcloud to be accessible + uri: + url: http://localhost:8808/status.php + status_code: 200 + register: nc_status + until: nc_status.status == 200 + retries: 30 + delay: 10 + + - name: Configure Nextcloud Redis cache + command: | + docker exec -u www-data next php occ config:system:set redis host --value=next-redis + args: + chdir: "{{ deployment_dir }}" + ignore_errors: yes + + - name: Configure Nextcloud Redis port + command: | + docker exec -u www-data next php occ config:system:set redis port --value=6379 + args: + chdir: "{{ deployment_dir }}" + ignore_errors: yes + + - name: Configure Nextcloud memcache + command: | + docker exec -u www-data next php occ config:system:set memcache.locking --value='\\OC\\Memcache\\Redis' + args: + chdir: "{{ deployment_dir }}" + ignore_errors: yes + + - name: Display deployment success + debug: + msg: | + ✓ Docker Compose stack deployed + ✓ All containers started + ✓ Nextcloud is accessible diff --git a/ansible/playbooks/06-configure-caddy.yml b/ansible/playbooks/06-configure-caddy.yml new file mode 100644 index 0000000..5a8c275 --- /dev/null +++ b/ansible/playbooks/06-configure-caddy.yml @@ -0,0 +1,48 @@ +--- +# Playbook 06: Configure Caddy +# Setup reverse proxy and obtain SSL certificates + +- name: Configure Caddy Reverse Proxy + hosts: all + become: yes + + tasks: + - name: Validate Caddyfile syntax + command: docker exec caddy caddy validate --config /etc/caddy/Caddyfile + args: + chdir: "{{ deployment_dir }}" + register: caddy_validate + failed_when: caddy_validate.rc != 0 + changed_when: false + + - name: Reload Caddy configuration + command: docker exec caddy caddy reload --config /etc/caddy/Caddyfile + args: + chdir: "{{ deployment_dir }}" + + - name: Wait for SSL certificates (may take 1-2 minutes) + pause: + seconds: 30 + prompt: "Waiting for Let's Encrypt to issue certificates..." + + - name: Test HTTPS endpoint for Nextcloud + uri: + url: "https://{{ subdomain_nextcloud }}.{{ domain }}/status.php" + validate_certs: yes + status_code: 200 + register: https_test + until: https_test.status == 200 + retries: 10 + delay: 10 + ignore_errors: yes + + - name: Display Caddy status + debug: + msg: | + ✓ Caddyfile validated + ✓ Caddy reloaded + {% if https_test.status == 200 %} + ✓ HTTPS working: https://{{ subdomain_nextcloud }}.{{ domain }} + {% else %} + ⚠ HTTPS check failed - verify DNS and firewall + {% endif %} diff --git a/ansible/playbooks/07-setup-backups.yml b/ansible/playbooks/07-setup-backups.yml new file mode 100644 index 0000000..b400dee --- /dev/null +++ b/ansible/playbooks/07-setup-backups.yml @@ -0,0 +1,87 @@ +--- +# Playbook 07: Setup Backups +# Configure automated backup system + +- name: Setup Backup System + hosts: all + become: yes + + tasks: + - name: Create backup script + copy: + dest: "{{ deployment_dir }}/backup.sh" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: '0755' + content: | + #!/bin/bash + # Nextcloud Stack Backup Script + set -euo pipefail + + BACKUP_DIR="{{ deployment_dir }}/backups" + DB_BACKUP_DIR="$BACKUP_DIR/database" + VOLUME_BACKUP_DIR="$BACKUP_DIR/volumes" + RETENTION_DAYS={{ backup_retention_days }} + DATE=$(date +%Y%m%d_%H%M%S) + LOG_FILE="$BACKUP_DIR/backup.log" + + log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" + } + + log "Starting backup process..." + + # Database backup + log "Backing up PostgreSQL database..." + docker exec next-db pg_dump -U {{ db_user }} {{ db_name }} | \ + gzip > "$DB_BACKUP_DIR/nextcloud_db_$DATE.sql.gz" + + if [ $? -eq 0 ]; then + log "Database backup completed: nextcloud_db_$DATE.sql.gz" + else + log "ERROR: Database backup failed!" + exit 1 + fi + + # Weekly volume backup (Sundays only) + if [ $(date +%u) -eq 7 ]; then + log "Weekly volume backup (Sunday)..." + docker exec -u www-data next php occ maintenance:mode --on + + tar -czf "$VOLUME_BACKUP_DIR/nextcloud_data_$DATE.tar.gz" \ + -C /var/lib/docker/volumes/nextcloud_nextcloud_data/_data . 2>/dev/null || true + + tar -czf "$VOLUME_BACKUP_DIR/configs_$DATE.tar.gz" \ + -C {{ deployment_dir }}/configs . 2>/dev/null || true + + docker exec -u www-data next php occ maintenance:mode --off + log "Volume backup completed" + fi + + # Cleanup old backups + log "Cleaning up backups older than $RETENTION_DAYS days..." + find "$DB_BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete + find "$VOLUME_BACKUP_DIR" -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete + + log "Backup process completed successfully!" + + - name: Create cron job for daily backups + cron: + name: "Nextcloud Stack Backup" + minute: "0" + hour: "3" + job: "{{ deployment_dir }}/backup.sh >> {{ deployment_dir }}/backups/backup.log 2>&1" + user: root + + - name: Run initial test backup + command: "{{ deployment_dir }}/backup.sh" + register: backup_test + ignore_errors: yes + + - name: Display backup status + debug: + msg: | + ✓ Backup script created + ✓ Cron job configured (daily 3:00 AM) + ✓ Test backup completed + Location: {{ deployment_dir }}/backups/ diff --git a/ansible/playbooks/08-post-deployment.yml b/ansible/playbooks/08-post-deployment.yml new file mode 100644 index 0000000..8b42b18 --- /dev/null +++ b/ansible/playbooks/08-post-deployment.yml @@ -0,0 +1,154 @@ +--- +# Playbook 08: Post-Deployment +# Final verification and configuration + +- name: Post-Deployment Tasks + hosts: all + become: yes + + tasks: + - name: Verify all containers are running + command: docker compose ps --format json + args: + chdir: "{{ deployment_dir }}" + register: container_status + changed_when: false + + - name: Check Nextcloud status + command: docker exec -u www-data next php occ status + args: + chdir: "{{ deployment_dir }}" + register: nc_status + changed_when: false + ignore_errors: yes + + - name: Install recommended Nextcloud apps + command: docker exec -u www-data next php occ app:install {{ item }} + args: + chdir: "{{ deployment_dir }}" + loop: + - calendar + - contacts + - tasks + - notes + ignore_errors: yes + + - name: Configure Nextcloud background jobs + command: docker exec -u www-data next php occ background:cron + args: + chdir: "{{ deployment_dir }}" + ignore_errors: yes + + - name: Setup Nextcloud cron job + cron: + name: "Nextcloud Background Jobs" + minute: "*/5" + job: "docker exec -u www-data next php /var/www/html/cron.php" + user: root + + - name: Get Tailscale IP (if activated) + command: tailscale ip -4 + register: tailscale_ip_result + changed_when: false + failed_when: false + + - name: Create deployment report + copy: + dest: "{{ deployment_dir }}/DEPLOYMENT.txt" + content: | + ════════════════════════════════════════════════════════════ + NEXTCLOUD STACK DEPLOYMENT REPORT + ════════════════════════════════════════════════════════════ + + Server: {{ inventory_hostname }} + IP Address: {{ ansible_host }} + Domain: {{ domain }} + Deployment Date: {{ ansible_date_time.iso8601 }} + + ──────────────────────────────────────────────────────────── + PUBLIC SERVICES (HTTPS) + ──────────────────────────────────────────────────────────── + • Nextcloud: https://{{ subdomain_nextcloud }}.{{ domain }} + • OnlyOffice: https://{{ subdomain_office }}.{{ domain }} + • Excalidraw: https://{{ subdomain_draw }}.{{ domain }} + • Obsidian: https://{{ subdomain_notes }}.{{ domain }} + + ──────────────────────────────────────────────────────────── + MANAGEMENT SERVICES (Tailscale only) + ──────────────────────────────────────────────────────────── + • Homarr: https://{{ subdomain_homarr }}.{{ domain }} + • Dockhand: https://{{ subdomain_dockhand }}.{{ domain }} + • Uptime Kuma: https://{{ subdomain_uptime }}.{{ domain }} + + ──────────────────────────────────────────────────────────── + CREDENTIALS + ──────────────────────────────────────────────────────────── + Nextcloud Admin User: {{ admin_user }} + Nextcloud Admin Password: [stored in Ansible vault] + + ──────────────────────────────────────────────────────────── + TAILSCALE + ──────────────────────────────────────────────────────────── + {% if tailscale_ip_result.rc == 0 %} + Status: Connected + Tailscale IP: {{ tailscale_ip_result.stdout }} + {% else %} + Status: Not activated + Activate with: sudo tailscale up + {% endif %} + + ──────────────────────────────────────────────────────────── + BACKUPS + ──────────────────────────────────────────────────────────── + Schedule: Daily at 3:00 AM + Location: {{ deployment_dir }}/backups/ + Retention: {{ backup_retention_days }} days + + ──────────────────────────────────────────────────────────── + USEFUL COMMANDS + ──────────────────────────────────────────────────────────── + View containers: cd {{ deployment_dir }} && docker compose ps + View logs: cd {{ deployment_dir }} && docker compose logs -f + Restart service: cd {{ deployment_dir }} && docker compose restart [service] + Manual backup: {{ deployment_dir }}/backup.sh + Nextcloud CLI: docker exec -u www-data next php occ [command] + + ════════════════════════════════════════════════════════════ + + - name: Display deployment summary + debug: + msg: | + ╔════════════════════════════════════════════════════════════╗ + ║ DEPLOYMENT COMPLETED SUCCESSFULLY! ║ + ╚════════════════════════════════════════════════════════════╝ + + Server: {{ inventory_hostname }} ({{ ansible_host }}) + Domain: {{ domain }} + + 📦 Public Services: + • Nextcloud: https://{{ subdomain_nextcloud }}.{{ domain }} + • OnlyOffice: https://{{ subdomain_office }}.{{ domain }} + • Excalidraw: https://{{ subdomain_draw }}.{{ domain }} + • Obsidian: https://{{ subdomain_notes }}.{{ domain }} + + 🔒 Management (Tailscale only): + • Homarr: https://{{ subdomain_homarr }}.{{ domain }} + • Dockhand: https://{{ subdomain_dockhand }}.{{ domain }} + • Uptime Kuma: https://{{ subdomain_uptime }}.{{ domain }} + + 👤 Nextcloud Admin: + Username: {{ admin_user }} + Password: [check vault] + + 💾 Backups: + Daily at 3:00 AM + Location: {{ deployment_dir }}/backups/ + + 📝 Next Steps: + 1. Login to Nextcloud and complete setup + 2. Setup Uptime Kuma monitoring (via Tailscale) + 3. Configure Homarr dashboard (via Tailscale) + 4. Review deployment report: {{ deployment_dir }}/DEPLOYMENT.txt + + Deployment report saved to: + {{ deployment_dir }}/DEPLOYMENT.txt diff --git a/ansible/playbooks/99-rollback.yml b/ansible/playbooks/99-rollback.yml new file mode 100644 index 0000000..80c9b06 --- /dev/null +++ b/ansible/playbooks/99-rollback.yml @@ -0,0 +1,41 @@ +--- +# Playbook 99: Emergency Rollback +# Stop and remove the deployment (keeps backups) + +- name: Emergency Rollback + hosts: all + become: yes + + tasks: + - name: Confirm rollback + pause: + prompt: | + ⚠️ WARNING: This will stop and remove all containers! + Backups in {{ deployment_dir }}/backups/ will be preserved. + Press ENTER to continue or Ctrl+C to cancel + + - name: Stop Docker Compose stack + command: docker compose down + args: + chdir: "{{ deployment_dir }}" + become_user: "{{ ansible_user }}" + ignore_errors: yes + + - name: Remove deployment directory (except backups) + shell: | + cd {{ deployment_dir }} + rm -rf configs data docker-compose.yml .env + ls -la + args: + warn: false + + - name: Display rollback status + debug: + msg: | + ✓ Containers stopped and removed + ✓ Deployment files removed + ✓ Backups preserved in {{ deployment_dir }}/backups/ + ✓ Docker volumes preserved (use 'docker volume ls' to see) + + To completely remove volumes (DELETES ALL DATA): + cd {{ deployment_dir }} && docker compose down -v diff --git a/ansible/playbooks/site.yml b/ansible/playbooks/site.yml new file mode 100644 index 0000000..a91574f --- /dev/null +++ b/ansible/playbooks/site.yml @@ -0,0 +1,26 @@ +--- +# Main Playbook - Nextcloud Stack Deployment +# This orchestrates the complete deployment process + +- name: Nextcloud Stack - Complete Deployment + hosts: all + gather_facts: yes + + pre_tasks: + - name: Display deployment banner + debug: + msg: | + ╔════════════════════════════════════════════════════════════╗ + ║ Nextcloud Stack Deployment Starting ║ + ║ Target: {{ inventory_hostname }} ({{ ansible_host }}) ║ + ║ Domain: {{ domain }} ║ + ╚════════════════════════════════════════════════════════════╝ + +- import_playbook: 01-preflight-checks.yml +- import_playbook: 02-system-setup.yml +- import_playbook: 03-docker-setup.yml +- import_playbook: 04-tailscale-setup.yml +- import_playbook: 05-deploy-stack.yml +- import_playbook: 06-configure-caddy.yml +- import_playbook: 07-setup-backups.yml +- import_playbook: 08-post-deployment.yml diff --git a/ansible/roles/caddy/templates/Caddyfile.j2 b/ansible/roles/caddy/templates/Caddyfile.j2 new file mode 100644 index 0000000..45aad9a --- /dev/null +++ b/ansible/roles/caddy/templates/Caddyfile.j2 @@ -0,0 +1,128 @@ +# Caddyfile - Generated by Ansible +# Domain: {{ domain }} + +# Global options +{ + email {{ user_email }} +} + +# ===== PUBLIC SERVICES ===== + +# Nextcloud +{{ subdomain_nextcloud }}.{{ domain }} { + reverse_proxy next:80 + + header { + Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + X-Content-Type-Options nosniff + X-Frame-Options SAMEORIGIN + Referrer-Policy no-referrer + X-XSS-Protection "1; mode=block" + -Server + } + + redir /.well-known/carddav /remote.php/dav 301 + redir /.well-known/caldav /remote.php/dav 301 + redir /.well-known/webfinger /index.php/.well-known/webfinger 301 + redir /.well-known/nodeinfo /index.php/.well-known/nodeinfo 301 + + request_body { + max_size 10GB + } +} + +# OnlyOffice Document Server +{{ subdomain_office }}.{{ domain }} { + reverse_proxy onlyoffice:80 + + request_body { + max_size 100MB + } + + header { + Strict-Transport-Security "max-age=31536000" + -Server + } +} + +# Excalidraw +{{ subdomain_draw }}.{{ domain }} { + reverse_proxy excalidraw:80 + + header { + Strict-Transport-Security "max-age=31536000" + -Server + } +} + +# Obsidian +{{ subdomain_notes }}.{{ domain }} { + reverse_proxy obsidian:3000 + + header { + Strict-Transport-Security "max-age=31536000" + -Server + } +} + +# ===== TAILSCALE-ONLY SERVICES ===== + +# Homarr Dashboard +{{ subdomain_homarr }}.{{ domain }} { + @tailscale { + remote_ip 100.64.0.0/10 + } + + handle @tailscale { + reverse_proxy homarr:7575 + } + + handle { + respond "Access Denied - Tailscale Required" 403 + abort + } +} + +# Dockhand Container Manager +{{ subdomain_dockhand }}.{{ domain }} { + @tailscale { + remote_ip 100.64.0.0/10 + } + + handle @tailscale { + reverse_proxy dockhand:3000 + } + + handle { + respond "Access Denied - Tailscale Required" 403 + abort + } +} + +# Uptime Kuma Monitoring +{{ subdomain_uptime }}.{{ domain }} { + @tailscale { + remote_ip 100.64.0.0/10 + } + + handle @tailscale { + reverse_proxy uptime-kuma:3001 + } + + handle { + respond "Access Denied - Tailscale Required" 403 + abort + } +} + +{% if enable_public_status %} +# Public Status Page +status.{{ domain }} { + reverse_proxy uptime-kuma:3001/status + + header { + Strict-Transport-Security "max-age=31536000" + -Server + } +} +{% endif %} diff --git a/ansible/roles/nextcloud_stack/templates/docker-compose.yml.j2 b/ansible/roles/nextcloud_stack/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..e67a840 --- /dev/null +++ b/ansible/roles/nextcloud_stack/templates/docker-compose.yml.j2 @@ -0,0 +1,229 @@ +services: + # ===== DATABASE LAYER ===== + + next-db: + image: docker.io/postgres:18 + container_name: next-db + restart: unless-stopped + environment: + - POSTGRES_DB={{ db_name }} + - POSTGRES_USER={{ db_user }} + - POSTGRES_PASSWORD={{ db_password }} + - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C + volumes: + - pg_data:/var/lib/postgresql/data + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=false" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U {{ db_user }}"] + interval: 10s + timeout: 5s + retries: 5 + + next-redis: + image: docker.io/redis:7-alpine + container_name: next-redis + restart: unless-stopped + command: redis-server --requirepass {{ redis_password }} --maxmemory 256mb --maxmemory-policy allkeys-lru + volumes: + - redis_data:/data + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=false" + healthcheck: + test: ["CMD", "redis-cli", "--raw", "incr", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + # ===== APPLICATION LAYER ===== + + next: + image: docker.io/nextcloud:latest + container_name: next + restart: unless-stopped + depends_on: + next-db: + condition: service_healthy + next-redis: + condition: service_healthy + mem_swappiness: -1 + environment: + - POSTGRES_DB={{ db_name }} + - POSTGRES_USER={{ db_user }} + - POSTGRES_PASSWORD={{ db_password }} + - POSTGRES_HOST=next-db + - REDIS_HOST=next-redis + - REDIS_HOST_PASSWORD={{ redis_password }} + - NEXTCLOUD_TRUSTED_DOMAINS={{ subdomain_nextcloud }}.{{ domain }} + - NEXTCLOUD_ADMIN_USER={{ admin_user }} + - NEXTCLOUD_ADMIN_PASSWORD={{ admin_password }} + - OVERWRITEPROTOCOL=https + - OVERWRITEHOST={{ subdomain_nextcloud }}.{{ domain }} + - TRUSTED_PROXIES=caddy + - PHP_MEMORY_LIMIT=512M + - PHP_UPLOAD_LIMIT=10G + volumes: + - nextcloud_data:/var/www/html + - {{ deployment_dir }}/configs/nextcloud:/var/www/html/config:Z + - nextcloud_apps:/var/www/html/custom_apps + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=false" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/status.php"] + interval: 30s + timeout: 10s + retries: 3 + + onlyoffice: + image: docker.io/onlyoffice/documentserver:latest + container_name: onlyoffice + restart: unless-stopped + environment: + - JWT_ENABLED=false + - JWT_HEADER=Authorization + - JWT_IN_BODY=true + volumes: + - onlyoffice_data:/var/www/onlyoffice/Data + - onlyoffice_logs:/var/log/onlyoffice + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.monitor-only=true" + + excalidraw: + image: docker.io/excalidraw/excalidraw:latest + container_name: excalidraw + restart: unless-stopped + environment: + - NODE_ENV=production + - TZ={{ timezone }} + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=true" + + obsidian: + image: lscr.io/linuxserver/obsidian:latest + container_name: obsidian + restart: unless-stopped + security_opt: + - seccomp:unconfined + environment: + - PUID=1000 + - PGID=1000 + - TZ={{ timezone }} + volumes: + - {{ deployment_dir }}/data/obsidian/config:/config:z + - {{ deployment_dir }}/data/obsidian/vault:/vault:z + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=true" + shm_size: "1gb" + + # ===== INFRASTRUCTURE LAYER ===== + + caddy: + image: docker.io/caddy:latest + container_name: caddy + restart: unless-stopped + ports: + - "80:80" + - "443:443" + - "443:443/udp" + volumes: + - {{ deployment_dir }}/configs/caddy/Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data + - caddy_config:/config + environment: + - DOMAIN={{ domain }} + - EMAIL={{ user_email }} + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=true" + + homarr: + image: ghcr.io/homarr-labs/homarr:latest + container_name: homarr + restart: unless-stopped + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - {{ deployment_dir }}/data/homarr:/appdata + environment: + - SECRET_ENCRYPTION_KEY={{ homarr_secret }} + - TZ={{ timezone }} + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=true" + + dockhand: + image: fnsys/dockhand:latest + container_name: dockhand + restart: unless-stopped + ports: + - "3003:3000" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - dockhand_data:/app/data + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=true" + + uptime-kuma: + image: louislam/uptime-kuma:latest + container_name: uptime-kuma + restart: unless-stopped + volumes: + - uptime_kuma_data:/app/data + environment: + - TZ={{ timezone }} + networks: + - nextcloud_network + labels: + - "com.centurylinklabs.watchtower.enable=true" + + watchtower: + image: containrrr/watchtower:latest + container_name: watchtower + restart: unless-stopped + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_LABEL_ENABLE=true + - WATCHTOWER_POLL_INTERVAL=86400 + - WATCHTOWER_ROLLING_RESTART=true + - WATCHTOWER_INCLUDE_RESTARTING=true + - TZ={{ timezone }} + networks: + - nextcloud_network + +# ===== PERSISTENT STORAGE ===== + +volumes: + pg_data: + redis_data: + nextcloud_data: + nextcloud_apps: + onlyoffice_data: + onlyoffice_logs: + caddy_data: + caddy_config: + dockhand_data: + uptime_kuma_data: + +# ===== NETWORKING ===== + +networks: + nextcloud_network: + name: nextcloud_network + driver: bridge diff --git a/ansible/roles/nextcloud_stack/templates/env.j2 b/ansible/roles/nextcloud_stack/templates/env.j2 new file mode 100644 index 0000000..445bc0e --- /dev/null +++ b/ansible/roles/nextcloud_stack/templates/env.j2 @@ -0,0 +1,31 @@ +# Environment Variables for Nextcloud Stack +# Generated by Ansible - DO NOT EDIT MANUALLY + +# Database Configuration +DB_NAME={{ db_name }} +DB_USER={{ db_user }} +DB_PASSWORD={{ db_password }} +DB_HOST=next-db + +# Redis Configuration +REDIS_PASSWORD={{ redis_password }} + +# Nextcloud Admin +NEXTCLOUD_ADMIN_USER={{ admin_user }} +NEXTCLOUD_ADMIN_PASSWORD={{ admin_password }} + +# Application Secrets +HOMARR_SECRET_KEY={{ homarr_secret }} + +# Domain Configuration +DOMAIN={{ domain }} +SUBDOMAIN_NEXTCLOUD={{ subdomain_nextcloud }} +SUBDOMAIN_OFFICE={{ subdomain_office }} + +# User Configuration +USER_EMAIL={{ user_email }} +TIMEZONE={{ timezone }} + +# UIDs/GIDs +PUID=1000 +PGID=1000 diff --git a/ansible/setup.sh b/ansible/setup.sh new file mode 100755 index 0000000..36d71ce --- /dev/null +++ b/ansible/setup.sh @@ -0,0 +1,463 @@ +#!/bin/bash +# +# Nextcloud Stack - Interactive Setup Script +# This script collects all configuration variables and generates Ansible inventory +# + +set -euo pipefail + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# Header +clear +echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║ Nextcloud Stack - Ansible Deployment Setup ║${NC}" +echo -e "${CYAN}║ Version 1.0 ║${NC}" +echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}" +echo "" +echo "This script will guide you through configuring your Nextcloud" +echo "deployment. Information will be encrypted using Ansible Vault." +echo "" + +# Arrays to store server data +declare -a SERVER_IPS +declare -a SERVER_HOSTNAMES +declare -a SERVER_DOMAINS +declare -a SERVER_SSH_USERS +declare -a SERVER_SSH_KEYS + +# Global variables +ADMIN_USER="" +ADMIN_PASSWORD="" +USER_NAME="" +USER_EMAIL="" +TIMEZONE="Europe/Zurich" +INSTALL_RCLONE="y" +ENABLE_PUBLIC_STATUS="n" +ALERT_EMAIL="" +TAILSCALE_AUTH_KEY="" + +# Subdomain defaults +SUBDOMAIN_NEXTCLOUD="cloud" +SUBDOMAIN_OFFICE="office" +SUBDOMAIN_DRAW="draw" +SUBDOMAIN_NOTES="notes" +SUBDOMAIN_HOMARR="home" +SUBDOMAIN_DOCKHAND="manage" +SUBDOMAIN_UPTIME="uptime" + +# Database defaults +DB_NAME="nextcloud" +DB_USER="nextcloud" + +# Generate random password +generate_password() { + openssl rand -base64 32 | tr -d "=+/" | cut -c1-32 +} + +# Validate IP address +validate_ip() { + local ip=$1 + if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + return 0 + else + return 1 + fi +} + +# Validate domain +validate_domain() { + local domain=$1 + if [[ $domain =~ ^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.[a-zA-Z]{2,}$ ]]; then + return 0 + else + return 1 + fi +} + +# Server Configuration +echo -e "${GREEN}=== Server Configuration ===${NC}" +echo "Enter server details (press Enter without input to finish):" +echo "" + +server_count=0 +while true; do + ((server_count++)) + echo -e "${BLUE}Server $server_count:${NC}" + + # IP Address + while true; do + read -p " IP address: " ip + if [[ -z "$ip" ]]; then + ((server_count--)) + break 2 + fi + if validate_ip "$ip"; then + SERVER_IPS+=("$ip") + break + else + echo -e "${RED} Invalid IP address. Please try again.${NC}" + fi + done + + # Hostname + read -p " Hostname [cloud$(printf "%02d" $server_count)]: " hostname + hostname=${hostname:-cloud$(printf "%02d" $server_count)} + SERVER_HOSTNAMES+=("$hostname") + + # Domain + while true; do + read -p " Domain (e.g., example.com): " domain + if [[ -z "$domain" ]]; then + echo -e "${RED} Domain is required. Please try again.${NC}" + elif validate_domain "$domain"; then + SERVER_DOMAINS+=("$domain") + break + else + echo -e "${RED} Invalid domain format. Please try again.${NC}" + fi + done + + # SSH User + read -p " SSH user [root]: " ssh_user + ssh_user=${ssh_user:-root} + SERVER_SSH_USERS+=("$ssh_user") + + # SSH Key + read -p " SSH key path [~/.ssh/id_rsa]: " ssh_key + ssh_key=${ssh_key:-~/.ssh/id_rsa} + # Expand tilde + ssh_key="${ssh_key/#\~/$HOME}" + SERVER_SSH_KEYS+=("$ssh_key") + + echo "" +done + +if [[ ${#SERVER_IPS[@]} -eq 0 ]]; then + echo -e "${RED}Error: At least one server is required.${NC}" + exit 1 +fi + +echo -e "${GREEN}✓ Configured ${#SERVER_IPS[@]} server(s)${NC}" +echo "" + +# User Information +echo -e "${GREEN}=== User Information ===${NC}" +read -p "Your name: " USER_NAME +while [[ -z "$USER_NAME" ]]; do + echo -e "${RED}Name is required.${NC}" + read -p "Your name: " USER_NAME +done + +read -p "Your email: " USER_EMAIL +while [[ -z "$USER_EMAIL" ]] || [[ ! "$USER_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; do + echo -e "${RED}Valid email is required.${NC}" + read -p "Your email: " USER_EMAIL +done + +read -p "Timezone [Europe/Zurich]: " TIMEZONE +TIMEZONE=${TIMEZONE:-Europe/Zurich} +echo "" + +# Nextcloud Admin Account +echo -e "${GREEN}=== Nextcloud Admin Account ===${NC}" +read -p "Admin username [admin]: " ADMIN_USER +ADMIN_USER=${ADMIN_USER:-admin} + +while true; do + read -sp "Admin password: " ADMIN_PASSWORD + echo "" + read -sp "Confirm password: " ADMIN_PASSWORD_CONFIRM + echo "" + + if [[ "$ADMIN_PASSWORD" == "$ADMIN_PASSWORD_CONFIRM" ]] && [[ ${#ADMIN_PASSWORD} -ge 8 ]]; then + break + elif [[ ${#ADMIN_PASSWORD} -lt 8 ]]; then + echo -e "${RED}Password must be at least 8 characters.${NC}" + else + echo -e "${RED}Passwords do not match. Please try again.${NC}" + fi +done +echo "" + +# Subdomain Configuration +echo -e "${GREEN}=== Subdomain Configuration ===${NC}" +echo "Press Enter to use defaults shown in brackets" +read -p "Nextcloud subdomain [cloud]: " SUBDOMAIN_NEXTCLOUD +SUBDOMAIN_NEXTCLOUD=${SUBDOMAIN_NEXTCLOUD:-cloud} + +read -p "OnlyOffice subdomain [office]: " SUBDOMAIN_OFFICE +SUBDOMAIN_OFFICE=${SUBDOMAIN_OFFICE:-office} + +read -p "Excalidraw subdomain [draw]: " SUBDOMAIN_DRAW +SUBDOMAIN_DRAW=${SUBDOMAIN_DRAW:-draw} + +read -p "Obsidian subdomain [notes]: " SUBDOMAIN_NOTES +SUBDOMAIN_NOTES=${SUBDOMAIN_NOTES:-notes} + +read -p "Homarr subdomain [home]: " SUBDOMAIN_HOMARR +SUBDOMAIN_HOMARR=${SUBDOMAIN_HOMARR:-home} + +read -p "Dockhand subdomain [manage]: " SUBDOMAIN_DOCKHAND +SUBDOMAIN_DOCKHAND=${SUBDOMAIN_DOCKHAND:-manage} + +read -p "Uptime Kuma subdomain [uptime]: " SUBDOMAIN_UPTIME +SUBDOMAIN_UPTIME=${SUBDOMAIN_UPTIME:-uptime} +echo "" + +# Database Configuration +echo -e "${GREEN}=== Database Configuration ===${NC}" +read -p "Database name [nextcloud]: " DB_NAME +DB_NAME=${DB_NAME:-nextcloud} + +read -p "Database user [nextcloud]: " DB_USER +DB_USER=${DB_USER:-nextcloud} + +echo "Generating secure passwords..." +DB_PASSWORD=$(generate_password) +REDIS_PASSWORD=$(generate_password) +HOMARR_SECRET=$(openssl rand -hex 32) +echo -e "${GREEN}✓ Passwords generated${NC}" +echo "" + +# Tailscale Configuration +echo -e "${GREEN}=== Tailscale Configuration ===${NC}" +read -p "Install Tailscale? (y/n) [y]: " install_tailscale +install_tailscale=${install_tailscale:-y} + +if [[ "$install_tailscale" == "y" ]]; then + read -p "Tailscale auth key (optional, press Enter to skip): " TAILSCALE_AUTH_KEY + if [[ -z "$TAILSCALE_AUTH_KEY" ]]; then + echo "Note: Tailscale will be installed but not activated." + echo " Activate manually with: sudo tailscale up" + fi +fi +echo "" + +# Monitoring Configuration +echo -e "${GREEN}=== Monitoring Configuration ===${NC}" +read -p "Email for uptime alerts: " ALERT_EMAIL +while [[ -z "$ALERT_EMAIL" ]] || [[ ! "$ALERT_EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; do + echo -e "${RED}Valid email is required.${NC}" + read -p "Email for uptime alerts: " ALERT_EMAIL +done + +read -p "Enable public status page? (y/n) [n]: " ENABLE_PUBLIC_STATUS +ENABLE_PUBLIC_STATUS=${ENABLE_PUBLIC_STATUS:-n} +echo "" + +# Backup Configuration +echo -e "${GREEN}=== Backup Configuration ===${NC}" +echo "Backup retention: 30 days (default)" +read -p "Install rclone for future remote backups? (y/n) [y]: " INSTALL_RCLONE +INSTALL_RCLONE=${INSTALL_RCLONE:-y} + +if [[ "$INSTALL_RCLONE" == "y" ]]; then + echo "Note: rclone will be installed but not configured." + echo " Configure later with: rclone config" +fi +echo "" + +# Ansible Vault Password +echo -e "${GREEN}=== Security ===${NC}" +echo "Create Ansible Vault password (will encrypt all secrets):" +while true; do + read -sp "Vault password: " VAULT_PASSWORD + echo "" + read -sp "Confirm: " VAULT_PASSWORD_CONFIRM + echo "" + + if [[ "$VAULT_PASSWORD" == "$VAULT_PASSWORD_CONFIRM" ]] && [[ ${#VAULT_PASSWORD} -ge 8 ]]; then + break + elif [[ ${#VAULT_PASSWORD} -lt 8 ]]; then + echo -e "${RED}Password must be at least 8 characters.${NC}" + else + echo -e "${RED}Passwords do not match. Please try again.${NC}" + fi +done +echo "" + +# Configuration Summary +echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║ CONFIGURATION SUMMARY ║${NC}" +echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}" +echo "" +echo "Servers: ${#SERVER_IPS[@]}" +for i in "${!SERVER_IPS[@]}"; do + echo " • ${SERVER_IPS[$i]} (${SERVER_DOMAINS[$i]})" +done +echo "" +echo "Services (per server):" +echo " • Nextcloud: https://$SUBDOMAIN_NEXTCLOUD." +echo " • OnlyOffice: https://$SUBDOMAIN_OFFICE." +echo " • Excalidraw: https://$SUBDOMAIN_DRAW." +echo " • Obsidian: https://$SUBDOMAIN_NOTES." +echo " • Homarr: https://$SUBDOMAIN_HOMARR. (Tailscale)" +echo " • Dockhand: https://$SUBDOMAIN_DOCKHAND. (Tailscale)" +echo " • Uptime Kuma: https://$SUBDOMAIN_UPTIME. (Tailscale)" +echo "" + +read -p "Proceed with these settings? (y/n): " confirm +if [[ "$confirm" != "y" ]]; then + echo "Setup cancelled." + exit 0 +fi +echo "" + +# Generate Configuration Files +echo "Generating configuration files..." + +# Create inventory directory +mkdir -p inventory/group_vars/all + +# Generate hosts.yml +cat >inventory/hosts.yml <>inventory/hosts.yml <inventory/group_vars/all/vars.yml <.vault_pass_temp + +# Create encrypted vault +echo "$VAULT_CONTENT" | ansible-vault encrypt --vault-password-file=.vault_pass_temp --output=inventory/group_vars/all/vault.yml + +# Clean up temp file +rm .vault_pass_temp + +echo -e "${GREEN}✓ Created: inventory/group_vars/all/vault.yml (encrypted)${NC}" +echo "" + +# Save vault password hint +echo "IMPORTANT: Save your vault password!" +echo "You will need it to run the playbook." +echo "" +echo "Vault password: **************** (hidden)" +echo "" + +# Final Instructions +echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║ READY TO DEPLOY! ║${NC}" +echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}" +echo "" +echo "Next steps:" +echo "" +echo "1. Review configuration (optional):" +echo " ansible-inventory --list" +echo "" +echo "2. Test connectivity:" +echo " ansible all -m ping --ask-vault-pass" +echo "" +echo "3. Deploy stack:" +echo " ansible-playbook playbooks/site.yml --ask-vault-pass" +echo "" +echo " OR use Makefile:" +echo " make deploy" +echo "" +echo "Estimated deployment time: 30-45 minutes per server" +echo "" +echo -e "${YELLOW}WARNING: Ensure DNS records are configured before deploying!${NC}" +echo " Let's Encrypt will fail if DNS is not pointing correctly." +echo "" +echo "Required DNS records for each server:" +for i in "${!SERVER_DOMAINS[@]}"; do + echo " ${SERVER_DOMAINS[$i]}:" + echo " $SUBDOMAIN_NEXTCLOUD.${SERVER_DOMAINS[$i]} → ${SERVER_IPS[$i]}" + echo " $SUBDOMAIN_OFFICE.${SERVER_DOMAINS[$i]} → ${SERVER_IPS[$i]}" + echo " $SUBDOMAIN_DRAW.${SERVER_DOMAINS[$i]} → ${SERVER_IPS[$i]}" + echo " $SUBDOMAIN_NOTES.${SERVER_DOMAINS[$i]} → ${SERVER_IPS[$i]}" + echo " $SUBDOMAIN_HOMARR.${SERVER_DOMAINS[$i]} → ${SERVER_IPS[$i]}" + echo " $SUBDOMAIN_DOCKHAND.${SERVER_DOMAINS[$i]} → ${SERVER_IPS[$i]}" + echo " $SUBDOMAIN_UPTIME.${SERVER_DOMAINS[$i]} → ${SERVER_IPS[$i]}" + echo "" +done +echo "" +echo "Setup complete! 🎉" diff --git a/kitty/.config/kitty/current-theme.conf b/kitty/.config/kitty/current-theme.conf index 4d4de88..a856d7f 100644 --- a/kitty/.config/kitty/current-theme.conf +++ b/kitty/.config/kitty/current-theme.conf @@ -1,56 +1,47 @@ -## name: Rosé Pine Moon -## author: mvllow -## license: MIT -## upstream: https://github.com/rose-pine/kitty/blob/main/dist/rose-pine-moon.conf -## blurb: All natural pine, faux fur and a bit of soho vibes for the classy minimalist +background #282828 +foreground #d4be98 -foreground #e0def4 -background #232136 -selection_foreground #e0def4 -selection_background #44415a +selection_background #d4be98 +selection_foreground #282828 -cursor #56526e -cursor_text_color #e0def4 +cursor #a89984 +cursor_text_color background -url_color #c4a7e7 +active_tab_background #282828 +active_tab_foreground #d4be98 +active_tab_font_style bold +inactive_tab_background #282828 +inactive_tab_foreground #a89984 +inactive_tab_font_style normal -active_tab_foreground #e0def4 -active_tab_background #393552 -inactive_tab_foreground #6e6a86 -inactive_tab_background #232136 +# Black +color0 #665c54 +color8 #928374 -active_border_color #3e8fb0 -inactive_border_color #44415a +# Red +color1 #ea6962 +color9 #ea6962 -# black -color0 #393552 -color8 #6e6a86 +# Green +color2 #a9b665 +color10 #a9b665 -# red -color1 #eb6f92 -color9 #eb6f92 +# Yellow +color3 #e78a4e +color11 #d8a657 -# green -color2 #3e8fb0 -color10 #3e8fb0 +# Blue +color4 #7daea3 +color12 #7daea3 -# yellow -color3 #f6c177 -color11 #f6c177 +# Magenta +color5 #d3869b +color13 #d3869b -# blue -color4 #9ccfd8 -color12 #9ccfd8 - -# magenta -color5 #c4a7e7 -color13 #c4a7e7 - -# cyan -color6 #ea9a97 -color14 #ea9a97 - -# white -color7 #e0def4 -color15 #e0def4 +# Cyan +color6 #89b482 +color14 #89b482 +# White +color7 #d4be98 +color15 #d4be98 diff --git a/kitty/.config/kitty/kitty.conf b/kitty/.config/kitty/kitty.conf index a809503..8ac10cc 100644 --- a/kitty/.config/kitty/kitty.conf +++ b/kitty/.config/kitty/kitty.conf @@ -1,5 +1,5 @@ # BEGIN_KITTY_THEME -# Rosé Pine Moon +# Gruvbox Material include current-theme.conf # END_KITTY_THEME # diff --git a/kitty/.config/kitty/kitty.conf.bak b/kitty/.config/kitty/kitty.conf.bak index 8ac10cc..e440f1e 100644 --- a/kitty/.config/kitty/kitty.conf.bak +++ b/kitty/.config/kitty/kitty.conf.bak @@ -1,5 +1,5 @@ # BEGIN_KITTY_THEME -# Gruvbox Material +# Kanagawa include current-theme.conf # END_KITTY_THEME # diff --git a/niri/.config/niri/config.kdl b/niri/.config/niri/config.kdl index 09fbf58..ba9b782 100644 --- a/niri/.config/niri/config.kdl +++ b/niri/.config/niri/config.kdl @@ -55,8 +55,8 @@ layout { } focus-ring { width 2 - active-color "#c4a7e7" - inactive-color "#a6adc8" + active-color "#7daea3" + inactive-color "#928374" } border { off @@ -80,6 +80,7 @@ spawn-at-startup "swaync" // spawn-at-startup "kanshi" spawn-at-startup "swww-daemon" spawn-at-startup "xwayland-satellite" +spawn-at-startup "gammastep" "-l" "47.38:8.54" "-t" "6000:4000" spawn-at-startup "kitty" spawn-at-startup "librewolf" spawn-at-startup "sh" "-c" "sleep 5 && exec swayidle -w timeout 300 hyprlock timeout 600 'niri msg action power-off-monitors' resume 'niri msg action power-on-monitors' timeout 3600 'systemctl suspend'" @@ -102,12 +103,23 @@ match app-id=r#"^org\.keepassxc\.KeePassXC$"# match app-id=r#"^org\.gnome\.World\.Secrets$"# block-out-from "screen-capture" } +window-rule { + match app-id="Bitwarden" + default-column-width { + proportion 0.6667 + } + open-floating true +} // terminal window-rule window-rule { - match app-id="^(zoom|us.zoom.Zoom)$" - exclude title="^.*Zoom Workplace" + match app-id="Zoom Workplace" open-floating true } +// window-rule { +// match app-id="^(zoom|us.zoom.Zoom)$" +// exclude title="^.*Zoom Workplace" +// open-floating true +// } window-rule { match at-startup=true app-id="kitty" @@ -173,6 +185,13 @@ window-rule { } open-floating true } +window-rule { + match app-id="floating_network-tui" + default-column-width { + proportion 0.6667 + } + open-floating true +} window-rule { geometry-corner-radius 5 clip-to-geometry true @@ -221,6 +240,9 @@ binds { Mod+Mod5+T hotkey-overlay-title="Open Wavemon" { spawn "kitty" "--class" "floating_wavemon" "-e" "wavemon" } + Mod+Mod5+Z hotkey-overlay-title="Open network-tui" { + spawn "kitty" "--class" "floating_network-tui" "-e" "network-tui" + } // Brightness Controll Mod+Ctrl+0 { spawn "sh" "-c" "~/scripts/layer_notify.sh 0" diff --git a/niri/.config/niri/waybar-niri/style.css b/niri/.config/niri/waybar-niri/style.css index f512ed6..d2d114f 100644 --- a/niri/.config/niri/waybar-niri/style.css +++ b/niri/.config/niri/waybar-niri/style.css @@ -26,7 +26,7 @@ button:hover { padding: 5px; } #workspaces button { - padding: 0 10px; + padding: 0 2px; background-color: transparent; color: @theme_fg_color; border-radius: 10px; diff --git a/nvim/.config/nvim/lua/current_theme.lua b/nvim/.config/nvim/lua/current_theme.lua index 5dfd683..03d5772 100644 --- a/nvim/.config/nvim/lua/current_theme.lua +++ b/nvim/.config/nvim/lua/current_theme.lua @@ -1,11 +1,10 @@ -vim.cmd.colorscheme("rose-pine") --- sonokai --- rose-pine --- onedark --- nightfox --- kanagawa --- gruvbox-mat --- everforest --- dracula --- carbonfox --- tokyonight +-- vim.cmd.colorscheme("rose-pine") +-- vim.cmd.colorscheme("sonokai") +-- vim.cmd.colorscheme("one-dark") +-- vim.cmd.colorscheme("nightfox") +-- vim.cmd.colorscheme("kanagawa") +vim.cmd.colorscheme("gruvbox-material") +-- vim.cmd.colorscheme("everforest") +-- vim.cmd.colorscheme("dracula") +-- vim.cmd.colorscheme("carbonfox") +-- vim.cmd.colorscheme("tokyonight") diff --git a/nvim/.config/nvim/lua/plugins/autopairs.lua b/nvim/.config/nvim/lua/plugins/autopairs.lua index 23a3981..d271243 100644 --- a/nvim/.config/nvim/lua/plugins/autopairs.lua +++ b/nvim/.config/nvim/lua/plugins/autopairs.lua @@ -13,26 +13,26 @@ return { local cmp = require("cmp") autopairs.setup({ - check_ts = true, -- Enable treesitter + check_ts = true, -- Enable treesitter ts_config = { - lua = { "string" }, -- Don't add pairs in lua string treesitter nodes + lua = { "string" }, -- Don't add pairs in lua string treesitter nodes javascript = { "template_string" }, -- Don't add pairs in JS template strings - java = false, -- Don't check treesitter on java + java = false, -- Don't check treesitter on java }, disable_filetype = { "TelescopePrompt", "vim" }, - disable_in_macro = true, -- Disable when recording or executing a macro + disable_in_macro = true, -- Disable when recording or executing a macro disable_in_visualblock = false, -- Disable when in visual block mode disable_in_replace_mode = true, ignored_next_char = [=[[%w%%%'%[%"%.%`%$]]=], enable_moveright = true, - enable_afterquote = true, -- Add bracket pairs after quote + enable_afterquote = true, -- Add bracket pairs after quote enable_check_bracket_line = true, -- Check bracket in same line enable_bracket_in_quote = true, - enable_abbr = false, -- Trigger abbreviation - break_undo = true, -- Switch for basic rule break undo sequence + enable_abbr = false, -- Trigger abbreviation + break_undo = true, -- Switch for basic rule break undo sequence check_comma = true, map_cr = true, - map_bs = true, -- Map the key + map_bs = true, -- Map the key map_c_h = false, -- Map the key to delete a pair map_c_w = false, -- Map to delete a pair if possible }) @@ -55,41 +55,41 @@ return { autopairs.add_rules({ Rule(" ", " ") - :with_pair(function(opts) - local pair = opts.line:sub(opts.col - 1, opts.col) - return vim.tbl_contains({ "()", "[]", "{}" }, pair) - end) - :with_move(cond.none()) - :with_cr(cond.none()) - :with_del(function(opts) - local col = vim.api.nvim_win_get_cursor(0)[2] - local context = opts.line:sub(col - 1, col + 2) - return vim.tbl_contains({ "( )", "[ ]", "{ }" }, context) - end), + :with_pair(function(opts) + local pair = opts.line:sub(opts.col - 1, opts.col) + return vim.tbl_contains({ "()", "[]", "{}" }, pair) + end) + :with_move(cond.none()) + :with_cr(cond.none()) + :with_del(function(opts) + local col = vim.api.nvim_win_get_cursor(0)[2] + local context = opts.line:sub(col - 1, col + 2) + return vim.tbl_contains({ "( )", "[ ]", "{ }" }, context) + end), Rule("", " )") - :with_pair(cond.none()) - :with_move(function(opts) - return opts.char == ")" - end) - :with_cr(cond.none()) - :with_del(cond.none()) - :use_key(")"), + :with_pair(cond.none()) + :with_move(function(opts) + return opts.char == ")" + end) + :with_cr(cond.none()) + :with_del(cond.none()) + :use_key(")"), Rule("", " }") - :with_pair(cond.none()) - :with_move(function(opts) - return opts.char == "}" - end) - :with_cr(cond.none()) - :with_del(cond.none()) - :use_key("}"), + :with_pair(cond.none()) + :with_move(function(opts) + return opts.char == "}" + end) + :with_cr(cond.none()) + :with_del(cond.none()) + :use_key("}"), Rule("", " ]") - :with_pair(cond.none()) - :with_move(function(opts) - return opts.char == "]" - end) - :with_cr(cond.none()) - :with_del(cond.none()) - :use_key("]"), + :with_pair(cond.none()) + :with_move(function(opts) + return opts.char == "]" + end) + :with_cr(cond.none()) + :with_del(cond.none()) + :use_key("]"), }) end, }, diff --git a/nvim/.config/nvim/lua/plugins/indent-blankline.lua b/nvim/.config/nvim/lua/plugins/indent-blankline.lua index 7a5bb04..e23335a 100644 --- a/nvim/.config/nvim/lua/plugins/indent-blankline.lua +++ b/nvim/.config/nvim/lua/plugins/indent-blankline.lua @@ -6,13 +6,25 @@ return { main = "ibl", event = { "BufReadPost", "BufNewFile" }, config = function() + -- Define highlights BEFORE setup() is called + local function set_highlights() + vim.api.nvim_set_hl(0, "IblIndent", { fg = "#313244" }) + vim.api.nvim_set_hl(0, "IblScope", { fg = "#5E81AC" }) + end + + set_highlights() + vim.api.nvim_create_autocmd("ColorScheme", { + pattern = "*", + callback = set_highlights, + }) + require("ibl").setup({ indent = { char = "▏", }, scope = { enabled = true, - char = "▏", -- Same character, different color + char = "▏", show_start = true, show_end = true, }, @@ -26,18 +38,6 @@ return { }, }, }) - - -- Very subtle gray for all indent lines - vim.api.nvim_set_hl(0, "IblIndent", { fg = "#313244" }) - - -- Soft accent for current scope (choose one): - -- Blue: - vim.api.nvim_set_hl(0, "IblScope", { fg = "#5E81AC" }) - - -- Or Purple: - -- vim.api.nvim_set_hl(0, "IblScope", { fg = "#B48EAD" }) - -- Or Green: - -- vim.api.nvim_set_hl(0, "IblScope", { fg = "#A3BE8C" }) end, }, } diff --git a/wofi/.config/wofi/style.css b/wofi/.config/wofi/style.css deleted file mode 120000 index a95bbce..0000000 --- a/wofi/.config/wofi/style.css +++ /dev/null @@ -1 +0,0 @@ -/home/liph/.config/wofi/themes/rose-pine-moon.css \ No newline at end of file diff --git a/wofi/.config/wofi/style.css b/wofi/.config/wofi/style.css new file mode 100644 index 0000000..2b8f79b --- /dev/null +++ b/wofi/.config/wofi/style.css @@ -0,0 +1,62 @@ +/* ============================================================ + Wofi Theme — Gruvbox Material + Based on sainnhe/gruvbox-material (Dark Hard variant) + Structure mirrored from provided rose-pine template + ============================================================ */ + +window { + margin: 0px; + background-color: #282828; + border-radius: 10px; + border: 2px solid #7daea3; + color: #d4be98; + font-family: "Monofur Nerd Font"; + font-size: 20px; +} + +#input { + margin: 5px; + border-radius: 10px; + border: none; + color: #d8a657; + background-color: #32302f; +} + +#inner-box { + margin: 5px; + border: none; + background-color: #32302f; + color: #282828; + border-radius: 5px; +} + +#outer-box { + margin: 15px; + border: none; + background-color: #282828; +} + +#scroll { + margin: 0px; + border: none; +} + +#text { + margin: 5px; + border: none; + color: #d4be98; +} + +#entry:selected { + background-color: #7daea3; + color: #282828; + border-radius: 5px; + outline: none; +} + +#entry:selected * { + background-color: #7daea3; + color: #282828; + border-radius: 5px; + outline: none; +} diff --git a/wofi/.config/wofi/themes/gruvbox-mat.css b/wofi/.config/wofi/themes/gruvbox-mat.css new file mode 100644 index 0000000..2b8f79b --- /dev/null +++ b/wofi/.config/wofi/themes/gruvbox-mat.css @@ -0,0 +1,62 @@ +/* ============================================================ + Wofi Theme — Gruvbox Material + Based on sainnhe/gruvbox-material (Dark Hard variant) + Structure mirrored from provided rose-pine template + ============================================================ */ + +window { + margin: 0px; + background-color: #282828; + border-radius: 10px; + border: 2px solid #7daea3; + color: #d4be98; + font-family: "Monofur Nerd Font"; + font-size: 20px; +} + +#input { + margin: 5px; + border-radius: 10px; + border: none; + color: #d8a657; + background-color: #32302f; +} + +#inner-box { + margin: 5px; + border: none; + background-color: #32302f; + color: #282828; + border-radius: 5px; +} + +#outer-box { + margin: 15px; + border: none; + background-color: #282828; +} + +#scroll { + margin: 0px; + border: none; +} + +#text { + margin: 5px; + border: none; + color: #d4be98; +} + +#entry:selected { + background-color: #7daea3; + color: #282828; + border-radius: 5px; + outline: none; +} + +#entry:selected * { + background-color: #7daea3; + color: #282828; + border-radius: 5px; + outline: none; +} diff --git a/wofi/.config/wofi/themes/kanagawa.css b/wofi/.config/wofi/themes/kanagawa.css new file mode 100644 index 0000000..51427d8 --- /dev/null +++ b/wofi/.config/wofi/themes/kanagawa.css @@ -0,0 +1,125 @@ +/* ============================================================ + Wofi Theme — Kanagawa + Based on rebelot/kanagawa.nvim (Wave variant) + ============================================================ */ + +* { + font-family: "JetBrains Mono", "Iosevka", monospace; + font-size: 13px; + transition: + background-color 0.1s ease, + color 0.1s ease; +} + +/* ── Main window ── */ +window { + background-color: #1f1f28; + border: 1px solid #2a2a37; + border-radius: 10px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.65); +} + +/* ── Outer layout wrapper ── */ +#outer-box { + background-color: transparent; + padding: 10px; +} + +/* ── Search input wrapper ── */ +#input { + background-color: #16161d; + color: #dcd7ba; + border: 1px solid #363646; + border-radius: 6px; + padding: 8px 12px; + margin-bottom: 8px; + caret-color: #e82424; + outline: none; +} + +#input:focus { + border-color: #7e9cd8; + box-shadow: 0 0 0 2px rgba(126, 156, 216, 0.15); +} + +#input image { + color: #54546d; +} + +/* ── Scrollable results area ── */ +#scroll { + background-color: transparent; +} + +#inner-box { + background-color: transparent; +} + +/* ── Individual entry row ── */ +#entry { + background-color: transparent; + color: #dcd7ba; + border-radius: 5px; + padding: 7px 10px; + margin: 2px 0; + border: 1px solid transparent; +} + +#entry:hover { + background-color: #2a2a37; + border-color: #363646; +} + +#entry:selected, +#entry.selected { + background-color: #223249; + border-color: #7e9cd8; + color: #7e9cd8; +} + +/* ── Entry image / icon ── */ +#entry image { + margin-right: 8px; + color: #98bb6c; +} + +#entry:selected image, +#entry.selected image { + color: #7e9cd8; +} + +/* ── Entry text label ── */ +#entry label { + color: inherit; +} + +/* ── Kanagawa accent palette ── */ +/* wave-red e82424 */ +/* autumn-yel e6c384 */ +/* spring-grn 98bb6c */ +/* crystal-blu 7e9cd8 */ +/* oni-violet 957fb8 */ +/* dragon-org ffa066 */ +/* spring-vio 938aa9 */ + +/* ── Scrollbar ── */ +scrollbar { + width: 4px; + background: transparent; +} + +scrollbar slider { + background-color: #363646; + border-radius: 2px; + min-height: 40px; +} + +scrollbar slider:hover { + background-color: #7e9cd8; +} + +/* ── No results message ── */ +#no-results { + color: #54546d; + padding: 12px; +} diff --git a/wofi/.config/wofi/themes/nightfox.css b/wofi/.config/wofi/themes/nightfox.css new file mode 100644 index 0000000..058b197 --- /dev/null +++ b/wofi/.config/wofi/themes/nightfox.css @@ -0,0 +1,126 @@ +/* ============================================================ + Wofi Theme — Nightfox + Based on EdenEast/nightfox.nvim (Nightfox variant) + ============================================================ */ + +* { + font-family: "JetBrains Mono", "Iosevka", monospace; + font-size: 13px; + transition: + background-color 0.1s ease, + color 0.1s ease; +} + +/* ── Main window ── */ +window { + background-color: #192330; + border: 1px solid #212e3f; + border-radius: 10px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); +} + +/* ── Outer layout wrapper ── */ +#outer-box { + background-color: transparent; + padding: 10px; +} + +/* ── Search input ── */ +#input { + background-color: #131a24; + color: #cdcecf; + border: 1px solid #29394f; + border-radius: 6px; + padding: 8px 12px; + margin-bottom: 8px; + caret-color: #c94f6d; + outline: none; +} + +#input:focus { + border-color: #719cd6; + box-shadow: 0 0 0 2px rgba(113, 156, 214, 0.15); +} + +#input image { + color: #3b4261; +} + +/* ── Scrollable results area ── */ +#scroll { + background-color: transparent; +} + +#inner-box { + background-color: transparent; +} + +/* ── Individual entry row ── */ +#entry { + background-color: transparent; + color: #cdcecf; + border-radius: 5px; + padding: 7px 10px; + margin: 2px 0; + border: 1px solid transparent; +} + +#entry:hover { + background-color: #212e3f; + border-color: #29394f; +} + +#entry:selected, +#entry.selected { + background-color: #1d3347; + border-color: #719cd6; + color: #719cd6; +} + +/* ── Entry image / icon ── */ +#entry image { + margin-right: 8px; + color: #81b29a; +} + +#entry:selected image, +#entry.selected image { + color: #719cd6; +} + +/* ── Entry text label ── */ +#entry label { + color: inherit; +} + +/* ── Nightfox accent palette ── */ +/* red c94f6d */ +/* orange f4a261 */ +/* yellow dbc074 */ +/* green 81b29a */ +/* cyan 63cdcf */ +/* blue 719cd6 */ +/* magenta 9d79d6 */ +/* pink d67ad2 */ + +/* ── Scrollbar ── */ +scrollbar { + width: 4px; + background: transparent; +} + +scrollbar slider { + background-color: #29394f; + border-radius: 2px; + min-height: 40px; +} + +scrollbar slider:hover { + background-color: #719cd6; +} + +/* ── No results message ── */ +#no-results { + color: #3b4261; + padding: 12px; +} diff --git a/wofi/.config/wofi/themes/one-dark.css b/wofi/.config/wofi/themes/one-dark.css new file mode 100644 index 0000000..b8d7ca6 --- /dev/null +++ b/wofi/.config/wofi/themes/one-dark.css @@ -0,0 +1,125 @@ +/* ============================================================ + Wofi Theme — One Dark + Based on Atom's One Dark (navarasu/onedark.nvim) + ============================================================ */ + +* { + font-family: "JetBrains Mono", "Iosevka", monospace; + font-size: 13px; + transition: + background-color 0.1s ease, + color 0.1s ease; +} + +/* ── Main window ── */ +window { + background-color: #282c34; + border: 1px solid #3e4451; + border-radius: 10px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55); +} + +/* ── Outer layout wrapper ── */ +#outer-box { + background-color: transparent; + padding: 10px; +} + +/* ── Search input ── */ +#input { + background-color: #21252b; + color: #abb2bf; + border: 1px solid #4b5263; + border-radius: 6px; + padding: 8px 12px; + margin-bottom: 8px; + caret-color: #e06c75; + outline: none; +} + +#input:focus { + border-color: #61afef; + box-shadow: 0 0 0 2px rgba(97, 175, 239, 0.15); +} + +#input image { + color: #5c6370; +} + +/* ── Scrollable results area ── */ +#scroll { + background-color: transparent; +} + +#inner-box { + background-color: transparent; +} + +/* ── Individual entry row ── */ +#entry { + background-color: transparent; + color: #abb2bf; + border-radius: 5px; + padding: 7px 10px; + margin: 2px 0; + border: 1px solid transparent; +} + +#entry:hover { + background-color: #2c313a; + border-color: #3e4451; +} + +#entry:selected, +#entry.selected { + background-color: #2d3750; + border-color: #61afef; + color: #61afef; +} + +/* ── Entry image / icon ── */ +#entry image { + margin-right: 8px; + color: #98c379; +} + +#entry:selected image, +#entry.selected image { + color: #61afef; +} + +/* ── Entry text label ── */ +#entry label { + color: inherit; +} + +/* ── One Dark accent palette ── */ +/* red e06c75 */ +/* orange d19a66 */ +/* yellow e5c07b */ +/* green 98c379 */ +/* cyan 56b6c2 */ +/* blue 61afef */ +/* magenta c678dd */ + +/* ── Scrollbar ── */ +scrollbar { + width: 4px; + background: transparent; +} + +scrollbar slider { + background-color: #4b5263; + border-radius: 2px; + min-height: 40px; +} + +scrollbar slider:hover { + background-color: #61afef; +} + +/* ── No results message ── */ +#no-results { + color: #5c6370; + padding: 12px; +} diff --git a/wofi/.config/wofi/themes/sonokai.css b/wofi/.config/wofi/themes/sonokai.css new file mode 100644 index 0000000..32f2886 --- /dev/null +++ b/wofi/.config/wofi/themes/sonokai.css @@ -0,0 +1,125 @@ +/* ============================================================ + Wofi Theme — Sonokai + Based on Sainnhe's Sonokai (Shusia variant) + ============================================================ */ + +* { + font-family: "JetBrains Mono", "Iosevka", monospace; + font-size: 13px; + transition: + background-color 0.1s ease, + color 0.1s ease; +} + +/* ── Main window ── */ +window { + background-color: #2d2a2e; + border: 1px solid #403e41; + border-radius: 10px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55); +} + +/* ── Outer layout wrapper ── */ +#outer-box { + background-color: transparent; + padding: 10px; +} + +/* ── Search input wrapper ── */ +#input { + background-color: #221f22; + color: #e3e1e4; + border: 1px solid #5b595c; + border-radius: 6px; + padding: 8px 12px; + margin-bottom: 8px; + caret-color: #ff6188; + outline: none; +} + +#input:focus { + border-color: #ff6188; + box-shadow: 0 0 0 2px rgba(255, 97, 136, 0.15); +} + +#input image { + /* search icon */ + color: #727072; +} + +/* ── Scrollable results area ── */ +#scroll { + background-color: transparent; +} + +#inner-box { + background-color: transparent; +} + +/* ── Individual entry row ── */ +#entry { + background-color: transparent; + color: #e3e1e4; + border-radius: 5px; + padding: 7px 10px; + margin: 2px 0; + border: 1px solid transparent; +} + +#entry:hover { + background-color: #3a3a3c; + border-color: #5b595c; +} + +#entry:selected, +#entry.selected { + background-color: #403e41; + border-color: #ff6188; + color: #ff6188; +} + +/* ── Entry image / icon ── */ +#entry image { + margin-right: 8px; + color: #a9dc76; +} + +#entry:selected image, +#entry.selected image { + color: #ff6188; +} + +/* ── Entry text label ── */ +#entry label { + color: inherit; +} + +/* ── Custom property colours (usable in sub-text) ── */ +/* accent-1 ff6188 pink */ +/* accent-2 fc9867 orange */ +/* accent-3 ffd866 yellow */ +/* accent-4 a9dc76 green */ +/* accent-5 78dce8 cyan */ +/* accent-6 ab9df2 purple */ + +/* ── Scrollbar ── */ +scrollbar { + width: 4px; + background: transparent; +} + +scrollbar slider { + background-color: #5b595c; + border-radius: 2px; + min-height: 40px; +} + +scrollbar slider:hover { + background-color: #ff6188; +} + +/* ── No results message ── */ +#no-results { + color: #727072; + padding: 12px; +} diff --git a/wofi/.config/wofi/themes/tokyo-night.css b/wofi/.config/wofi/themes/tokyo-night.css new file mode 100644 index 0000000..d679b49 --- /dev/null +++ b/wofi/.config/wofi/themes/tokyo-night.css @@ -0,0 +1,30 @@ +window { + background-color: rgb(26, 27, 38); + border-radius: 0.5em; +} + +#input { + padding: 0.7em; + border-radius: 0.5em 0.5em 0 0; + background-color: #2d2e40; + color: #c0caf5; + border: none; +} + +#text { + color: #c0caf5; +} + +#entry { + padding: 0.7em; + color: #c0caf5; +} + +#entry:selected { + background-color: #7aa2f7; +} + +#text:selected { + color: #eee; + font-weight: bold; +} diff --git a/yazi/.config/yazi/flavors/dracula.yazi b/yazi/.config/yazi/flavors/dracula.yazi new file mode 160000 index 0000000..1b1a8d1 --- /dev/null +++ b/yazi/.config/yazi/flavors/dracula.yazi @@ -0,0 +1 @@ +Subproject commit 1b1a8d1083474defa9e4c1c3de4db9576f23175f diff --git a/yazi/.config/yazi/flavors/everforest-medium.yazi/LICENSE b/yazi/.config/yazi/flavors/everforest-medium.yazi/LICENSE new file mode 100644 index 0000000..978c8ef --- /dev/null +++ b/yazi/.config/yazi/flavors/everforest-medium.yazi/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Chromium Oxide + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/yazi/.config/yazi/flavors/everforest-medium.yazi/LICENSE-tmtheme b/yazi/.config/yazi/flavors/everforest-medium.yazi/LICENSE-tmtheme new file mode 100644 index 0000000..020b42d --- /dev/null +++ b/yazi/.config/yazi/flavors/everforest-medium.yazi/LICENSE-tmtheme @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Mitchell Hanberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/yazi/.config/yazi/flavors/everforest-medium.yazi/README.md b/yazi/.config/yazi/flavors/everforest-medium.yazi/README.md new file mode 100644 index 0000000..95029b5 --- /dev/null +++ b/yazi/.config/yazi/flavors/everforest-medium.yazi/README.md @@ -0,0 +1,45 @@ +
+ Yazi logo +
+ +

+ Example Flavor for Yazi +

+ +## 👀 Preview + + + +## 🎨 Installation + +```bash +ya pkg add Chromium-3-Oxide/everforest-medium +``` + +Or: + +```bash +ya pack -a Chromium-3-Oxide/everforest-medium +``` + +## ⚙️ Usage + +Add the these lines to your `theme.toml` configuration file to use it: + +```toml +[flavor] +dark = "everforest-medium" +``` + +For Yazi versions before 0.4: + +```toml +[flavor] +use = "everforest-medium" +``` + +## 📜 License + +The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed. + +Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details. diff --git a/yazi/.config/yazi/flavors/everforest-medium.yazi/flavor.toml b/yazi/.config/yazi/flavors/everforest-medium.yazi/flavor.toml new file mode 100644 index 0000000..6ba84b7 --- /dev/null +++ b/yazi/.config/yazi/flavors/everforest-medium.yazi/flavor.toml @@ -0,0 +1,229 @@ +# vim:fileencoding=utf-8:foldmethod=marker + +# : Manager {{{ + +[mgr] +cwd = { fg = "#7fbbb3" } + +# Hovered +hovered = { reversed = true } +preview_hovered = { underline = true } + +# Find +find_keyword = { fg = "#dbbc7f", bold = true, italic = true, underline = true } +find_position = { fg = "#d699b6", bg = "reset", bold = true, italic = true } + +# Symlink +symlink_target = { italic = true } + +# Marker +marker_copied = { fg = "#a7c080", bg = "#a7c080" } +marker_cut = { fg = "#e67e80", bg = "#e67e80" } +marker_marked = { fg = "#7fbbb3", bg = "#7fbbb3" } +marker_selected = { fg = "#dbbc7f", bg = "#dbbc7f" } + +# Count +count_copied = { fg = "#343f44", bg = "#a7c080" } +count_cut = { fg = "#343f44", bg = "#e67e80" } +count_selected = { fg = "#343f44", bg = "#dbbc7f" } + +# Border +border_symbol = "│" +border_style = { fg = "#4f585e" } + +# Highlighting +syntect_theme = "" + +# : }}} + + +# : Tabs {{{ + +[tabs] +active = { bg = "#7fbbb3", bold = true } +inactive = { fg = "#7fbbb3", bg = "#4f585e" } + +# Separator +sep_inner = { open = "", close = "" } +sep_outer = { open = "", close = "" } + +# : }}} + + +# : Mode {{{ + +[mode] +normal_main = { fg = "#3d484d", bg = "#a7c080", bold = true } +normal_alt = { fg = "#7fbbb3", bg = "#4f585e", bold = true } + +# Select mode +select_main = { fg = "#3d484d", bg = "#e67e80", bold = true } +select_alt = { fg = "#7fbbb3", bg = "#4f585e", bold = true } + +# Unset mode +unset_main = { fg = "#3d484d", bg = "#7fbbb3", bold = true } +unset_alt = { fg = "#7fbbb3", bg = "#4f585e", bold = true } + +# : }}} + + +# : Status bar {{{ + +[status] +overall = {} +sep_left = { open = "", close = "" } +sep_right = { open = "", close = "" } + +# Permissions +permissions_s = { fg = "#2d353b" } +permissions_t = { fg = "#a7c080" } +permissions_r = { fg = "#dbbc7f" } +permissions_w = { fg = "#e67e80" } +permissions_x = { fg = "#7fbbb3" } + +# Progress +progress_label = { bold = true } +progress_normal = { fg = "#7fbbb3", bg = "#232a2e" } +progress_error = { fg = "#e67e80", bg = "#232a2e" } + +# : }}} + + +# : Which {{{ + +[which] +cols = 3 +mask = { bg = "#2d353b" } +cand = { fg = "#7fbbb3" } +rest = { fg = "#2d353b" } +desc = { fg = "#d699b6" } +separator = "  " +separator_style = { fg = "#2d353b" } + +# : }}} + + +# : Confirmation {{{ + +[confirm] +border = { fg = "#7fbbb3" } +title = { fg = "#7fbbb3" } +body = {} +list = {} +btn_yes = { reversed = true } +btn_no = {} +btn_labels = [ " [Y]es ", " (N)o " ] + +# : }}} + + +# : Spotter {{{ + +[spot] +border = { fg = "#7fbbb3" } +title = { fg = "#7fbbb3" } + +# Table +tbl_col = { fg = "#7fbbb3" } +tbl_cell = { fg = "#dbbc7f", reversed = true } + +# : }}} + + +# : Notification {{{ + +[notify] +title_info = { fg = "#a7c080" } +title_warn = { fg = "#dbbc7f" } +title_error = { fg = "#e67e80" } + +# Icons +icon_info = "" +icon_warn = "" +icon_error = "" + +# : }}} + + +# : Picker {{{ + +[pick] +border = { fg = "#7fbbb3" } +active = { fg = "#d699b6", bold = true } +inactive = {} + +# : }}} + + +# : Input {{{ + +[input] +border = { fg = "#7fbbb3" } +title = {} +value = {} +selected = { reversed = true } + +# : }}} + + +# : Completion {{{ + +[cmp] +border = { fg = "#7fbbb3" } +active = { reversed = true } +inactive = {} + +# Icons +icon_file = "" +icon_folder = "" +icon_command = "" + +# : }}} + + +# : Task manager {{{ + +[tasks] +border = { fg = "#7fbbb3" } +title = {} +hovered = { fg = "#d699b6", underline = true } + +# : }}} + + +# : Help menu {{{ + +[help] +on = { fg = "#7fbbb3" } +run = { fg = "#d699b6" } +desc = {} +hovered = { reversed = true, bold = true } +footer = { fg = "#2d353b", bg = "#d3c6aa" } + +# : }}} + + +# : File-specific styles {{{ + +[filetype] + +rules = [ + # Images + { mime = "image/*", fg = "#7fbbb3" }, + + # Media + { mime = "{audio,video}/*", fg = "#d699b6" }, + + # Archives + { mime = "application/*zip", fg = "#e67e80" }, + { mime = "application/x-{tar,bzip*,7z-compressed,xz,rar}", fg = "#e67e80" }, + + # Documents + { mime = "application/{pdf,doc,rtf,vnd.*}", fg = "#7fbbb3" }, + + # Fallback + { name = "*", fg = "#83c092" }, + { name = "*/", fg = "#a7c080" } +] + +# : }}} diff --git a/yazi/.config/yazi/flavors/everforest-medium.yazi/preview.png b/yazi/.config/yazi/flavors/everforest-medium.yazi/preview.png new file mode 100644 index 0000000..d3960cc Binary files /dev/null and b/yazi/.config/yazi/flavors/everforest-medium.yazi/preview.png differ diff --git a/yazi/.config/yazi/flavors/everforest-medium.yazi/tmtheme.xml b/yazi/.config/yazi/flavors/everforest-medium.yazi/tmtheme.xml new file mode 100644 index 0000000..e063c97 --- /dev/null +++ b/yazi/.config/yazi/flavors/everforest-medium.yazi/tmtheme.xml @@ -0,0 +1,3186 @@ + + + + + name + Everforest Dark + settings + + + settings + + accent + #a7c080 + background + #2d353b + caret + #d3c6aa + foreground + #d3c6aa + lineHighlight + #3d484d90 + selection + #475258c0 + activeGuide + #9aa79d20 + findHighlight + #899c4040 + misspelling + #da6362 + + + + name + GitGutter deleted + scope + markup.deleted.git_gutter + settings + + foreground + #e67e80a0 + + + + name + GitGutter inserted + scope + markup.inserted.git_gutter + settings + + foreground + #a7c080a0 + + + + name + GitGutter changed + scope + markup.changed.git_gutter + settings + + foreground + #7fbbb3a0 + + + + name + GitGutter untracked + scope + markup.untracked.git_gutter + settings + + foreground + #dbbc7fa0 + + + + name + GitGutter ignored + scope + markup.ignored.git_gutter + settings + + foreground + #4f585e + + + + name + GitGutter comment + scope + comment.line.annotation.git_gutter + settings + + foreground + + name + Comment + scope + comment, string.comment, punctuation.definition.comment + settings + + foreground + #859289 + fontStyle + italic + + + + + + name + Keyword + scope + keyword, storage.type.function, storage.type.class, storage.type.enum, storage.type.interface, storage.type.property, keyword.operator.new, keyword.operator.expression, keyword.operator.new, keyword.operator.delete, storage.type.extends + settings + + foreground + #e67e80 + + + + name + Debug + scope + keyword.other.debugger + settings + + foreground + #e67e80 + + + + name + Storage + scope + storage, modifier, keyword.var, entity.name.tag, keyword.control.case, keyword.control.switch + settings + + foreground + #e69875 + + + + name + Operator + scope + keyword.operator + settings + + foreground + #e69875 + + + + name + String + scope + string, punctuation.definition.string.end, punctuation.definition.string.begin, punctuation.definition.string.template.begin, punctuation.definition.string.template.end + settings + + foreground + #dbbc7f + + + + name + Attribute + scope + entity.other.attribute-name + settings + + foreground + #dbbc7f + + + + name + String Escape + scope + constant.character.escape, punctuation.quasi.element, punctuation.definition.template-expression, punctuation.section.embedded, storage.type.format, constant.other.placeholder, constant.other.placeholder, variable.interpolation + settings + + foreground + #a7c080 + + + + name + Function + scope + entity.name.function, support.function, meta.function, meta.function-call, meta.definition.method + settings + + foreground + #a7c080 + + + + name + Preproc + scope + keyword.control.at-rule, keyword.control.import, keyword.control.export, storage.type.namespace, punctuation.decorator, keyword.control.directive, keyword.preprocessor, punctuation.definition.preprocessor, punctuation.definition.directive, keyword.other.import, keyword.other.package, entity.name.type.namespace, entity.name.scope-resolution, keyword.other.using, keyword.package, keyword.import, keyword.map + settings + + foreground + #83c092 + + + + name + Annotation + scope + storage.type.annotation + settings + + foreground + #83c092 + + + + name + Label + scope + entity.name.label, constant.other.label + settings + + foreground + #83c092 + + + + name + Modules + scope + support.module, support.node, support.other.module, support.type.object.module, entity.name.type.module, entity.name.type.class.module, keyword.control.module + settings + + foreground + #83c092 + + + + name + Type + scope + storage.type, support.type, entity.name.type, keyword.type + settings + + foreground + #7fbbb3 + + + + name + Class + scope + entity.name.type.class, support.class, entity.name.class, entity.other.inherited-class, storage.class + settings + + foreground + #7fbbb3 + + + + name + Number + scope + constant.numeric + settings + + foreground + #d699b6 + + + + name + Boolean + scope + constant.language.boolean + settings + + foreground + #d699b6 + + + + name + Macro + scope + entity.name.function.preprocessor + settings + + foreground + #d699b6 + + + + name + Special identifier + scope + variable.language.this, variable.language.self, variable.language.super, keyword.other.this, variable.language.special, constant.language.null, constant.language.undefined, constant.language.nan + settings + + foreground + #d699b6 + + + + name + Constant + scope + constant.language, support.constant + settings + + foreground + #d699b6 + + + + name + Identifier + scope + variable, support.variable, meta.definition.variable + settings + + foreground + #d3c6aa + + + + name + Property + scope + variable.object.property, support.variable.property, variable.other.property, variable.other.object.property, variable.other.enummember, variable.other.member, meta.object-literal.key + settings + + foreground + #d3c6aa + + + + name + Delimiter + scope + punctuation, meta.brace, meta.delimiter, meta.bracket + settings + + foreground + #d3c6aa + + + + name + Markdown heading1 + scope + heading.1.markdown, markup.heading.setext.1.markdown + settings + + foreground + #e67e80 + fontStyle + bold + + + + name + Markdown heading2 + scope + heading.2.markdown, markup.heading.setext.2.markdown + settings + + foreground + #e69875 + fontStyle + bold + + + + name + Markdown heading3 + scope + heading.3.markdown + settings + + foreground + #dbbc7f + fontStyle + bold + + + + name + Markdown heading4 + scope + heading.4.markdown + settings + + foreground + #a7c080 + fontStyle + bold + + + + name + Markdown heading5 + scope + heading.5.markdown + settings + + foreground + #7fbbb3 + fontStyle + bold + + + + name + Markdown heading6 + scope + heading.6.markdown + settings + + foreground + #d699b6 + fontStyle + bold + + + + name + Markdown heading delimiter + scope + punctuation.definition.heading.markdown + settings + + foreground + #859289 + fontStyle + regular + + + + name + Markdown link + scope + string.other.link.title.markdown, constant.other.reference.link.markdown, string.other.link.description.markdown + settings + + foreground + #d699b6 + fontStyle + regular + + + + name + Markdown link text + scope + markup.underline.link.image.markdown, markup.underline.link.markdown + settings + + foreground + #a7c080 + fontStyle + underline + + + + name + Markdown delimiter + scope + punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.italic.markdown, punctuation.definition.quote.begin.markdown, punctuation.definition.metadata.markdown, punctuation.separator.key-value.markdown, punctuation.definition.constant.markdown + settings + + foreground + #859289 + + + + name + Markdown bold delimiter + scope + punctuation.definition.bold.markdown + settings + + foreground + #859289 + fontStyle + regular + + + + name + Markdown separator delimiter + scope + meta.separator.markdown, punctuation.definition.constant.begin.markdown, punctuation.definition.constant.end.markdown + settings + + foreground + #859289 + fontStyle + bold + + + + name + Markdown italic + scope + markup.italic + settings + + fontStyle + italic + + + + name + Markdown bold + scope + markup.bold + settings + + fontStyle + bold + + + + name + Markdown bold italic + scope + markup.bold markup.italic, markup.italic markup.bold + settings + + fontStyle + italic bold + + + + name + Markdown code delimiter + scope + punctuation.definition.markdown, punctuation.definition.raw.markdown + settings + + foreground + #dbbc7f + + + + name + Markdown code type + scope + fenced_code.block.language + settings + + foreground + #dbbc7f + + + + name + Markdown code block + scope + markup.fenced_code.block.markdown, markup.inline.raw.string.markdown + settings + + foreground + #a7c080 + + + + name + Markdown list mark + scope + punctuation.definition.list.begin.markdown + settings + + foreground + #e67e80 + + + + name + reStructuredText heading + scope + punctuation.definition.heading.restructuredtext + settings + + foreground + #e69875 + fontStyle + bold + + + + name + reStructuredText delimiter + scope + punctuation.definition.field.restructuredtext, punctuation.separator.key-value.restructuredtext, punctuation.definition.directive.restructuredtext, punctuation.definition.constant.restructuredtext, punctuation.definition.italic.restructuredtext, punctuation.definition.table.restructuredtext + settings + + foreground + #859289 + + + + name + reStructuredText delimiter bold + scope + punctuation.definition.bold.restructuredtext + settings + + foreground + #859289 + fontStyle + regular + + + + name + reStructuredText aqua + scope + entity.name.tag.restructuredtext, punctuation.definition.link.restructuredtext, punctuation.definition.raw.restructuredtext, punctuation.section.raw.restructuredtext + settings + + foreground + #83c092 + + + + name + reStructuredText purple + scope + constant.other.footnote.link.restructuredtext + settings + + foreground + #d699b6 + + + + name + reStructuredText red + scope + support.directive.restructuredtext + settings + + foreground + #e67e80 + + + + name + reStructuredText green + scope + entity.name.directive.restructuredtext, markup.raw.restructuredtext, markup.raw.inner.restructuredtext, string.other.link.title.restructuredtext + settings + + foreground + #a7c080 + + + + name + LaTex delimiter + scope + punctuation.definition.function.latex, punctuation.definition.function.tex, punctuation.definition.keyword.latex, constant.character.newline.tex, punctuation.definition.keyword.tex + settings + + foreground + #859289 + + + + name + LaTex red + scope + support.function.be.latex + settings + + foreground + #e67e80 + + + + name + LaTex orange + scope + support.function.section.latex, keyword.control.table.cell.latex, keyword.control.table.newline.latex + settings + + foreground + #e69875 + + + + name + LaTex yellow + scope + support.class.latex, variable.parameter.latex, variable.parameter.function.latex, variable.parameter.definition.label.latex, constant.other.reference.label.latex + settings + + foreground + #dbbc7f + + + + name + LaTex purple + scope + keyword.control.preamble.latex + settings + + foreground + #d699b6 + + + + name + Html grey + scope + punctuation.separator.namespace.xml + settings + + foreground + #859289 + + + + name + Html orange + scope + entity.name.tag.html, entity.name.tag.xml, entity.name.tag.localname.xml + settings + + foreground + #e69875 + + + + name + Html yellow + scope + entity.other.attribute-name.html, entity.other.attribute-name.xml, entity.other.attribute-name.localname.xml + settings + + foreground + #dbbc7f + + + + name + Html green + scope + string.quoted.double.html, string.quoted.single.html, punctuation.definition.string.begin.html, punctuation.definition.string.end.html, punctuation.separator.key-value.html, punctuation.definition.string.begin.xml, punctuation.definition.string.end.xml, string.quoted.double.xml, string.quoted.single.xml, punctuation.definition.tag.begin.html, punctuation.definition.tag.end.html, punctuation.definition.tag.xml, meta.tag.xml, meta.tag.preprocessor.xml, meta.tag.other.html, meta.tag.block.any.html, meta.tag.inline.any.html + settings + + foreground + #a7c080 + + + + name + Html purple + scope + variable.language.documentroot.xml, meta.tag.sgml.doctype.xml + settings + + foreground + #d699b6 + + + + name + Proto yellow + scope + storage.type.proto + settings + + foreground + #dbbc7f + + + + name + Proto green + scope + string.quoted.double.proto.syntax, string.quoted.single.proto.syntax, string.quoted.double.proto, string.quoted.single.proto + settings + + foreground + #a7c080 + + + + name + Proto aqua + scope + entity.name.class.proto, entity.name.class.message.proto + settings + + foreground + #83c092 + + + + name + CSS grey + scope + punctuation.definition.entity.css, punctuation.separator.key-value.css, punctuation.terminator.rule.css, punctuation.separator.list.comma.css + settings + + foreground + #859289 + + + + name + CSS red + scope + entity.other.attribute-name.class.css + settings + + foreground + #e67e80 + + + + name + CSS orange + scope + keyword.other.unit + settings + + foreground + #e69875 + + + + name + CSS yellow + scope + entity.other.attribute-name.pseudo-class.css, entity.other.attribute-name.pseudo-element.css + settings + + foreground + #dbbc7f + + + + name + CSS green + scope + string.quoted.single.css, string.quoted.double.css, support.constant.property-value.css, meta.property-value.css, punctuation.definition.string.begin.css, punctuation.definition.string.end.css, constant.numeric.css, support.constant.font-name.css, variable.parameter.keyframe-list.css + settings + + foreground + #a7c080 + + + + name + CSS aqua + scope + support.type.property-name.css + settings + + foreground + #83c092 + + + + name + CSS blue + scope + support.type.vendored.property-name.css + settings + + foreground + #7fbbb3 + + + + name + CSS purple + scope + entity.name.tag.css, entity.other.keyframe-offset.css, punctuation.definition.keyword.css, keyword.control.at-rule.keyframes.css, meta.selector.css + settings + + foreground + #d699b6 + + + + name + SASS grey + scope + punctuation.definition.entity.scss, punctuation.separator.key-value.scss, punctuation.terminator.rule.scss, punctuation.separator.list.comma.scss + settings + + foreground + #859289 + + + + name + SASS orange + scope + keyword.control.at-rule.keyframes.scss + settings + + foreground + #e69875 + + + + name + SASS yellow + scope + punctuation.definition.interpolation.begin.bracket.curly.scss, punctuation.definition.interpolation.end.bracket.curly.scss + settings + + foreground + #dbbc7f + + + + name + SASS green + scope + punctuation.definition.string.begin.scss, punctuation.definition.string.end.scss, string.quoted.double.scss, string.quoted.single.scss, constant.character.css.sass, meta.property-value.scss + settings + + foreground + #a7c080 + + + + name + SASS purple + scope + keyword.control.at-rule.include.scss, keyword.control.at-rule.use.scss, keyword.control.at-rule.mixin.scss, keyword.control.at-rule.extend.scss, keyword.control.at-rule.import.scss + settings + + foreground + #d699b6 + + + + name + Stylus white + scope + meta.function.stylus + settings + + foreground + #d3c6aa + + + + name + Stylus yellow + scope + entity.name.function.stylus + settings + + foreground + #dbbc7f + + + + name + JavaScript white + scope + string.unquoted.js + settings + + foreground + #d3c6aa + + + + name + JavaScript grey + scope + punctuation.accessor.js, punctuation.separator.key-value.js, punctuation.separator.label.js, keyword.operator.accessor.js + settings + + foreground + #859289 + + + + name + JavaScript red + scope + punctuation.definition.block.tag.jsdoc + settings + + foreground + #e67e80 + + + + name + JavaScript orange + scope + storage.type.js, storage.type.function.arrow.js + settings + + foreground + #e69875 + + + + name + JSX white + scope + JSXNested + settings + + foreground + #d3c6aa + + + + name + JSX green + scope + punctuation.definition.tag.jsx, entity.other.attribute-name.jsx, punctuation.definition.tag.begin.js.jsx, punctuation.definition.tag.end.js.jsx, entity.other.attribute-name.js.jsx + settings + + foreground + #a7c080 + + + + name + TypeScript white + scope + entity.name.type.module.ts + settings + + foreground + #d3c6aa + + + + name + TypeScript grey + scope + keyword.operator.type.annotation.ts, punctuation.accessor.ts, punctuation.separator.key-value.ts + settings + + foreground + #859289 + + + + name + TypeScript green + scope + punctuation.definition.tag.directive.ts, entity.other.attribute-name.directive.ts + settings + + foreground + #a7c080 + + + + name + TypeScript aqua + scope + entity.name.type.ts, entity.name.type.interface.ts, entity.other.inherited-class.ts, entity.name.type.alias.ts, entity.name.type.class.ts, entity.name.type.enum.ts + settings + + foreground + #83c092 + + + + name + TypeScript orange + scope + storage.type.ts, storage.type.function.arrow.ts, storage.type.type.ts + settings + + foreground + #e69875 + + + + name + TypeScript blue + scope + entity.name.type.module.ts + settings + + foreground + #7fbbb3 + + + + name + TypeScript purple + scope + keyword.control.import.ts, keyword.control.export.ts, storage.type.namespace.ts + settings + + foreground + #d699b6 + + + + name + TSX white + scope + entity.name.type.module.tsx + settings + + foreground + #d3c6aa + + + + name + TSX grey + scope + keyword.operator.type.annotation.tsx, punctuation.accessor.tsx, punctuation.separator.key-value.tsx + settings + + foreground + #859289 + + + + name + TSX green + scope + punctuation.definition.tag.directive.tsx, entity.other.attribute-name.directive.tsx, punctuation.definition.tag.begin.tsx, punctuation.definition.tag.end.tsx, entity.other.attribute-name.tsx + settings + + foreground + #a7c080 + + + + name + TSX aqua + scope + entity.name.type.tsx, entity.name.type.interface.tsx, entity.other.inherited-class.tsx, entity.name.type.alias.tsx, entity.name.type.class.tsx, entity.name.type.enum.tsx + settings + + foreground + #83c092 + + + + name + TSX blue + scope + entity.name.type.module.tsx + settings + + foreground + #7fbbb3 + + + + name + TSX purple + scope + keyword.control.import.tsx, keyword.control.export.tsx, storage.type.namespace.tsx + settings + + foreground + #d699b6 + + + + name + TSX orange + scope + storage.type.tsx, storage.type.function.arrow.tsx, storage.type.type.tsx, support.class.component.tsx + settings + + foreground + #e69875 + + + + name + CoffeeScript orange + scope + storage.type.function.coffee + settings + + foreground + #e69875 + + + + name + PureScript white + scope + meta.type-signature.purescript + settings + + foreground + #d3c6aa + + + + name + PureScript orange + scope + keyword.other.double-colon.purescript, keyword.other.arrow.purescript, keyword.other.big-arrow.purescript + settings + + foreground + #e69875 + + + + name + PureScript yellow + scope + entity.name.function.purescript + settings + + foreground + #dbbc7f + + + + name + PureScript green + scope + string.quoted.single.purescript, string.quoted.double.purescript, punctuation.definition.string.begin.purescript, punctuation.definition.string.end.purescript, string.quoted.triple.purescript, entity.name.type.purescript + settings + + foreground + #a7c080 + + + + name + PureScript purple + scope + support.other.module.purescript + settings + + foreground + #d699b6 + + + + name + Dart grey + scope + punctuation.dot.dart + settings + + foreground + #859289 + + + + name + Dart orange + scope + storage.type.primitive.dart + settings + + foreground + #e69875 + + + + name + Dart yellow + scope + support.class.dart + settings + + foreground + #dbbc7f + + + + name + Dart green + scope + entity.name.function.dart, string.interpolated.single.dart, string.interpolated.double.dart + settings + + foreground + #a7c080 + + + + name + Dart blue + scope + variable.language.dart + settings + + foreground + #7fbbb3 + + + + name + Dart purple + scope + keyword.other.import.dart, storage.type.annotation.dart + settings + + foreground + #d699b6 + + + + name + Pug red + scope + entity.other.attribute-name.class.pug + settings + + foreground + #e67e80 + + + + name + Pug orange + scope + storage.type.function.pug + settings + + foreground + #e69875 + + + + name + Pug aqua + scope + entity.other.attribute-name.tag.pug + settings + + foreground + #83c092 + + + + name + Pug purple + scope + entity.name.tag.pug, storage.type.import.include.pug + settings + + foreground + #d699b6 + + + + name + C white + scope + meta.function-call.c, storage.modifier.array.bracket.square.c, meta.function.definition.parameters.c + settings + + foreground + #d3c6aa + + + + name + C grey + scope + punctuation.separator.dot-access.c, constant.character.escape.line-continuation.c + settings + + foreground + #859289 + + + + name + C red + scope + keyword.control.directive.include.c, punctuation.definition.directive.c, keyword.control.directive.pragma.c, keyword.control.directive.line.c, keyword.control.directive.define.c, keyword.control.directive.conditional.c, keyword.control.directive.diagnostic.error.c, keyword.control.directive.undef.c, keyword.control.directive.conditional.ifdef.c, keyword.control.directive.endif.c, keyword.control.directive.conditional.ifndef.c, keyword.control.directive.conditional.if.c, keyword.control.directive.else.c + settings + + foreground + #e67e80 + + + + name + C orange + scope + punctuation.separator.pointer-access.c + settings + + foreground + #e69875 + + + + name + C aqua + scope + variable.other.member.c + settings + + foreground + #83c092 + + + + name + C++ white + scope + meta.function-call.cpp, storage.modifier.array.bracket.square.cpp, meta.function.definition.parameters.cpp, meta.body.function.definition.cpp + settings + + foreground + #d3c6aa + + + + name + C++ grey + scope + punctuation.separator.dot-access.cpp, constant.character.escape.line-continuation.cpp + settings + + foreground + #859289 + + + + name + C++ red + scope + keyword.control.directive.include.cpp, punctuation.definition.directive.cpp, keyword.control.directive.pragma.cpp, keyword.control.directive.line.cpp, keyword.control.directive.define.cpp, keyword.control.directive.conditional.cpp, keyword.control.directive.diagnostic.error.cpp, keyword.control.directive.undef.cpp, keyword.control.directive.conditional.ifdef.cpp, keyword.control.directive.endif.cpp, keyword.control.directive.conditional.ifndef.cpp, keyword.control.directive.conditional.if.cpp, keyword.control.directive.else.cpp, storage.type.namespace.definition.cpp, keyword.other.using.directive.cpp, storage.type.struct.cpp + settings + + foreground + #e67e80 + + + + name + C++ orange + scope + punctuation.separator.pointer-access.cpp, punctuation.section.angle-brackets.begin.template.call.cpp, punctuation.section.angle-brackets.end.template.call.cpp + settings + + foreground + #e69875 + + + + name + C++ aqua + scope + variable.other.member.cpp + settings + + foreground + #83c092 + + + + name + C# red + scope + keyword.other.using.cs + settings + + foreground + #e67e80 + + + + name + C# yellow + scope + keyword.type.cs, constant.character.escape.cs, punctuation.definition.interpolation.begin.cs, punctuation.definition.interpolation.end.cs + settings + + foreground + #dbbc7f + + + + name + C# green + scope + string.quoted.double.cs, string.quoted.single.cs, punctuation.definition.string.begin.cs, punctuation.definition.string.end.cs + settings + + foreground + #a7c080 + + + + name + C# aqua + scope + variable.other.object.property.cs + settings + + foreground + #83c092 + + + + name + C# purple + scope + entity.name.type.namespace.cs + settings + + foreground + #d699b6 + + + + name + F# white + scope + keyword.symbol.fsharp, constant.language.unit.fsharp + settings + + foreground + #d3c6aa + + + + name + F# yellow + scope + keyword.format.specifier.fsharp, entity.name.type.fsharp + settings + + foreground + #dbbc7f + + + + name + F# green + scope + string.quoted.double.fsharp, string.quoted.single.fsharp, punctuation.definition.string.begin.fsharp, punctuation.definition.string.end.fsharp + settings + + foreground + #a7c080 + + + + name + F# blue + scope + entity.name.section.fsharp + settings + + foreground + #7fbbb3 + + + + name + F# purple + scope + support.function.attribute.fsharp + settings + + foreground + #d699b6 + + + + name + Java grey + scope + punctuation.separator.java, punctuation.separator.period.java + settings + + foreground + #859289 + + + + name + Java red + scope + keyword.other.import.java, keyword.other.package.java + settings + + foreground + #e67e80 + + + + name + Java orange + scope + storage.type.function.arrow.java, keyword.control.ternary.java + settings + + foreground + #e69875 + + + + name + Java aqua + scope + variable.other.property.java + settings + + foreground + #83c092 + + + + name + Java purple + scope + variable.language.wildcard.java, storage.modifier.import.java, storage.type.annotation.java, punctuation.definition.annotation.java, storage.modifier.package.java, entity.name.type.module.java + settings + + foreground + #d699b6 + + + + name + Kotlin red + scope + keyword.other.import.kotlin + settings + + foreground + #e67e80 + + + + name + Kotlin orange + scope + storage.type.kotlin + settings + + foreground + #e69875 + + + + name + Kotlin aqua + scope + constant.language.kotlin + settings + + foreground + #83c092 + + + + name + Kotlin purple + scope + entity.name.package.kotlin, storage.type.annotation.kotlin + settings + + foreground + #d699b6 + + + + name + Scala purple + scope + entity.name.package.scala + settings + + foreground + #d699b6 + + + + name + Scala blue + scope + constant.language.scala + settings + + foreground + #7fbbb3 + + + + name + Scala aqua + scope + entity.name.import.scala + settings + + foreground + #83c092 + + + + name + Scala green + scope + string.quoted.double.scala, string.quoted.single.scala, punctuation.definition.string.begin.scala, punctuation.definition.string.end.scala, string.quoted.double.interpolated.scala, string.quoted.single.interpolated.scala, string.quoted.triple.scala + settings + + foreground + #a7c080 + + + + name + Scala yellow + scope + entity.name.class, entity.other.inherited-class.scala + settings + + foreground + #dbbc7f + + + + name + Scala orange + scope + keyword.declaration.stable.scala, keyword.other.arrow.scala + settings + + foreground + #e69875 + + + + name + Scala red + scope + keyword.other.import.scala + settings + + foreground + #e67e80 + + + + name + Groovy white + scope + keyword.operator.navigation.groovy, meta.method.body.java, meta.definition.method.groovy, meta.definition.method.signature.java + settings + + foreground + #d3c6aa + + + + name + Scala grey + scope + punctuation.separator.groovy + settings + + foreground + #859289 + + + + name + Scala red + scope + keyword.other.import.groovy, keyword.other.package.groovy, keyword.other.import.static.groovy + settings + + foreground + #e67e80 + + + + name + Groovy orange + scope + storage.type.def.groovy + settings + + foreground + #e69875 + + + + name + Groovy green + scope + variable.other.interpolated.groovy, meta.method.groovy + settings + + foreground + #a7c080 + + + + name + Groovy aqua + scope + storage.modifier.import.groovy, storage.modifier.package.groovy + settings + + foreground + #83c092 + + + + name + Groovy purple + scope + storage.type.annotation.groovy + settings + + foreground + #d699b6 + + + + name + Go red + scope + keyword.type.go + settings + + foreground + #e67e80 + + + + name + Go aqua + scope + entity.name.package.go + settings + + foreground + #83c092 + + + + name + Go purple + scope + keyword.import.go, keyword.package.go + settings + + foreground + #d699b6 + + + + name + Rust white + scope + entity.name.type.mod.rust + settings + + foreground + #d3c6aa + + + + name + Rust grey + scope + keyword.operator.path.rust, keyword.operator.member-access.rust + settings + + foreground + #859289 + + + + name + Rust orange + scope + storage.type.rust + settings + + foreground + #e69875 + + + + name + Rust aqua + scope + support.constant.core.rust + settings + + foreground + #83c092 + + + + name + Rust purple + scope + meta.attribute.rust, variable.language.rust, storage.type.module.rust + settings + + foreground + #d699b6 + + + + name + Swift white + scope + meta.function-call.swift, support.function.any-method.swift + settings + + foreground + #d3c6aa + + + + name + Swift aqua + scope + support.variable.swift + settings + + foreground + #83c092 + + + + name + PHP white + scope + keyword.operator.class.php + settings + + foreground + #d3c6aa + + + + name + PHP orange + scope + storage.type.trait.php + settings + + foreground + #e69875 + + + + name + PHP aqua + scope + constant.language.php, support.other.namespace.php + settings + + foreground + #83c092 + + + + name + PHP blue + scope + storage.type.modifier.access.control.public.cpp, storage.type.modifier.access.control.private.cpp + settings + + foreground + #7fbbb3 + + + + name + PHP purple + scope + keyword.control.import.include.php, storage.type.php + settings + + foreground + #d699b6 + + + + name + Python white + scope + meta.function-call.arguments.python + settings + + foreground + #d3c6aa + + + + name + Python grey + scope + punctuation.definition.decorator.python, punctuation.separator.period.python + settings + + foreground + #859289 + + + + name + Python aqua + scope + constant.language.python + settings + + foreground + #83c092 + + + + name + Python purple + scope + keyword.control.import.python, keyword.control.import.from.python + settings + + foreground + #d699b6 + + + + name + Lua aqua + scope + constant.language.lua + settings + + foreground + #83c092 + + + + name + Lua blue + scope + entity.name.class.lua + settings + + foreground + #7fbbb3 + + + + name + Ruby white + scope + meta.function.method.with-arguments.ruby + settings + + foreground + #d3c6aa + + + + name + Ruby grey + scope + punctuation.separator.method.ruby + settings + + foreground + #859289 + + + + name + Ruby orange + scope + keyword.control.pseudo-method.ruby, storage.type.variable.ruby + settings + + foreground + #e69875 + + + + name + Ruby green + scope + keyword.other.special-method.ruby + settings + + foreground + #a7c080 + + + + name + Ruby purple + scope + keyword.control.module.ruby, punctuation.definition.constant.ruby + settings + + foreground + #d699b6 + + + + name + Ruby yellow + scope + string.regexp.character-class.ruby,string.regexp.interpolated.ruby,punctuation.definition.character-class.ruby,string.regexp.group.ruby, punctuation.section.regexp.ruby, punctuation.definition.group.ruby + settings + + foreground + #dbbc7f + + + + name + Ruby blue + scope + variable.other.constant.ruby + settings + + foreground + #7fbbb3 + + + + name + Haskell orange + scope + keyword.other.arrow.haskell, keyword.other.big-arrow.haskell, keyword.other.double-colon.haskell + settings + + foreground + #e69875 + + + + name + Haskell yellow + scope + storage.type.haskell + settings + + foreground + #dbbc7f + + + + name + Haskell green + scope + constant.other.haskell, string.quoted.double.haskell, string.quoted.single.haskell, punctuation.definition.string.begin.haskell, punctuation.definition.string.end.haskell + settings + + foreground + #a7c080 + + + + name + Haskell blue + scope + entity.name.function.haskell + settings + + foreground + #7fbbb3 + + + + name + Haskell aqua + scope + entity.name.namespace, meta.preprocessor.haskell + settings + + foreground + #83c092 + + + + name + Julia red + scope + keyword.control.import.julia, keyword.control.export.julia + settings + + foreground + #e67e80 + + + + name + Julia orange + scope + keyword.storage.modifier.julia + settings + + foreground + #e69875 + + + + name + Julia aqua + scope + constant.language.julia + settings + + foreground + #83c092 + + + + name + Julia purple + scope + support.function.macro.julia + settings + + foreground + #d699b6 + + + + name + Elm white + scope + keyword.other.period.elm + settings + + foreground + #d3c6aa + + + + name + Elm yellow + scope + storage.type.elm + settings + + foreground + #dbbc7f + + + + name + R orange + scope + keyword.other.r + settings + + foreground + #e69875 + + + + name + R green + scope + entity.name.function.r, variable.function.r + settings + + foreground + #a7c080 + + + + name + R aqua + scope + constant.language.r + settings + + foreground + #83c092 + + + + name + R purple + scope + entity.namespace.r + settings + + foreground + #d699b6 + + + + name + Erlang grey + scope + punctuation.separator.module-function.erlang, punctuation.section.directive.begin.erlang + settings + + foreground + #859289 + + + + name + Erlang red + scope + keyword.control.directive.erlang, keyword.control.directive.define.erlang + settings + + foreground + #e67e80 + + + + name + Erlang yellow + scope + entity.name.type.class.module.erlang + settings + + foreground + #dbbc7f + + + + name + Erlang green + scope + string.quoted.double.erlang, string.quoted.single.erlang, punctuation.definition.string.begin.erlang, punctuation.definition.string.end.erlang + settings + + foreground + #a7c080 + + + + name + Erlang purple + scope + keyword.control.directive.export.erlang, keyword.control.directive.module.erlang, keyword.control.directive.import.erlang, keyword.control.directive.behaviour.erlang + settings + + foreground + #d699b6 + + + + name + Elixir aqua + scope + variable.other.readwrite.module.elixir, punctuation.definition.variable.elixir + settings + + foreground + #83c092 + + + + name + Elixir blue + scope + constant.language.elixir + settings + + foreground + #7fbbb3 + + + + name + Elixir purple + scope + keyword.control.module.elixir + settings + + foreground + #d699b6 + + + + name + OCaml white + scope + entity.name.type.value-signature.ocaml + settings + + foreground + #d3c6aa + + + + name + OCaml orange + scope + keyword.other.ocaml + settings + + foreground + #e69875 + + + + name + OCaml aqua + scope + constant.language.variant.ocaml + settings + + foreground + #83c092 + + + + name + Perl red + scope + storage.type.sub.perl, storage.type.declare.routine.perl + settings + + foreground + #e67e80 + + + + name + Lisp white + scope + meta.function.lisp + settings + + foreground + #d3c6aa + + + + name + Lisp red + scope + storage.type.function-type.lisp + settings + + foreground + #e67e80 + + + + name + Lisp green + scope + keyword.constant.lisp + settings + + foreground + #a7c080 + + + + name + Lisp aqua + scope + entity.name.function.lisp + settings + + foreground + #83c092 + + + + name + Clojure green + scope + constant.keyword.clojure, support.variable.clojure, meta.definition.variable.clojure + settings + + foreground + #a7c080 + + + + name + Clojure purple + scope + entity.global.clojure + settings + + foreground + #d699b6 + + + + name + Clojure blue + scope + entity.name.function.clojure + settings + + foreground + #7fbbb3 + + + + name + Shell white + scope + meta.scope.if-block.shell, meta.scope.group.shell + settings + + foreground + #d3c6aa + + + + name + Shell yellow + scope + support.function.builtin.shell, entity.name.function.shell + settings + + foreground + #dbbc7f + + + + name + Shell green + scope + string.quoted.double.shell, string.quoted.single.shell, punctuation.definition.string.begin.shell, punctuation.definition.string.end.shell, string.unquoted.heredoc.shell + settings + + foreground + #a7c080 + + + + name + Shell purple + scope + keyword.control.heredoc-token.shell, variable.other.normal.shell, punctuation.definition.variable.shell, variable.other.special.shell, variable.other.positional.shell, variable.other.bracket.shell + settings + + foreground + #d699b6 + + + + name + Fish red + scope + support.function.builtin.fish + settings + + foreground + #e67e80 + + + + name + Fish orange + scope + support.function.unix.fish + settings + + foreground + #e69875 + + + + name + Fish blue + scope + variable.other.normal.fish, punctuation.definition.variable.fish, variable.other.fixed.fish, variable.other.special.fish + settings + + foreground + #7fbbb3 + + + + name + Fish green + scope + string.quoted.double.fish, punctuation.definition.string.end.fish, punctuation.definition.string.begin.fish, string.quoted.single.fish + settings + + foreground + #a7c080 + + + + name + Fish purple + scope + constant.character.escape.single.fish + settings + + foreground + #d699b6 + + + + name + PowerShell grey + scope + punctuation.definition.variable.powershell + settings + + foreground + #859289 + + + + name + PowerShell yellow + scope + entity.name.function.powershell, support.function.attribute.powershell, support.function.powershell + settings + + foreground + #dbbc7f + + + + name + PowerShell green + scope + string.quoted.single.powershell, string.quoted.double.powershell, punctuation.definition.string.begin.powershell, punctuation.definition.string.end.powershell, string.quoted.double.heredoc.powershell + settings + + foreground + #a7c080 + + + + name + PowerShell aqua + scope + variable.other.member.powershell + settings + + foreground + #83c092 + + + + name + GraphQL white + scope + string.unquoted.alias.graphql + settings + + foreground + #d3c6aa + + + + name + GraphQL red + scope + keyword.type.graphql + settings + + foreground + #e67e80 + + + + name + GraphQL purple + scope + entity.name.fragment.graphql + settings + + foreground + #d699b6 + + + + name + Makefile orange + scope + entity.name.function.target.makefile + settings + + foreground + #e69875 + + + + name + Makefile yellow + scope + variable.other.makefile + settings + + foreground + #dbbc7f + + + + name + Makefile green + scope + meta.scope.prerequisites.makefile + settings + + foreground + #a7c080 + + + + name + CMake green + scope + string.source.cmake + settings + + foreground + #a7c080 + + + + name + CMake aqua + scope + entity.source.cmake + settings + + foreground + #83c092 + + + + name + CMake purple + scope + storage.source.cmake + settings + + foreground + #d699b6 + + + + name + VimL grey + scope + punctuation.definition.map.viml + settings + + foreground + #859289 + + + + name + VimL orange + scope + storage.type.map.viml + settings + + foreground + #e69875 + + + + name + VimL green + scope + constant.character.map.viml, constant.character.map.key.viml + settings + + foreground + #a7c080 + + + + name + VimL blue + scope + constant.character.map.special.viml + settings + + foreground + #7fbbb3 + + + + name + Tmux green + scope + constant.language.tmux, constant.numeric.tmux + settings + + foreground + #a7c080 + + + + name + Dockerfile orange + scope + entity.name.function.package-manager.dockerfile + settings + + foreground + #e69875 + + + + name + Dockerfile yellow + scope + keyword.operator.flag.dockerfile + settings + + foreground + #dbbc7f + + + + name + Dockerfile green + scope + string.quoted.double.dockerfile, string.quoted.single.dockerfile + settings + + foreground + #a7c080 + + + + name + Dockerfile aqua + scope + constant.character.escape.dockerfile + settings + + foreground + #83c092 + + + + name + Dockerfile purple + scope + entity.name.type.base-image.dockerfile, entity.name.image.dockerfile + settings + + foreground + #d699b6 + + + + name + Diff grey + scope + punctuation.definition.separator.diff + settings + + foreground + #859289 + + + + name + Diff red + scope + markup.deleted.diff, punctuation.definition.deleted.diff + settings + + foreground + #e67e80 + + + + name + Diff orange + scope + meta.diff.range.context, punctuation.definition.range.diff + settings + + foreground + #e69875 + + + + name + Diff yellow + scope + meta.diff.header.from-file + settings + + foreground + #dbbc7f + + + + name + Diff green + scope + markup.inserted.diff, punctuation.definition.inserted.diff + settings + + foreground + #a7c080 + + + + name + Diff blue + scope + markup.changed.diff, punctuation.definition.changed.diff + settings + + foreground + #7fbbb3 + + + + name + Diff purple + scope + punctuation.definition.from-file.diff + settings + + foreground + #d699b6 + + + + name + Git red + scope + entity.name.section.group-title.ini, punctuation.definition.entity.ini + settings + + foreground + #e67e80 + + + + name + Git orange + scope + punctuation.separator.key-value.ini + settings + + foreground + #e69875 + + + + name + Git green + scope + string.quoted.double.ini, string.quoted.single.ini, punctuation.definition.string.begin.ini, punctuation.definition.string.end.ini + settings + + foreground + #a7c080 + + + + name + Git aqua + scope + keyword.other.definition.ini + settings + + foreground + #83c092 + + + + name + SQL yellow + scope + support.function.aggregate.sql + settings + + foreground + #dbbc7f + + + + name + SQL green + scope + string.quoted.single.sql, punctuation.definition.string.end.sql, punctuation.definition.string.begin.sql, string.quoted.double.sql + settings + + foreground + #a7c080 + + + + name + GraphQL yellow + scope + support.type.graphql + settings + + foreground + #dbbc7f + + + + name + GraphQL blue + scope + variable.parameter.graphql + settings + + foreground + #7fbbb3 + + + + name + GraphQL aqua + scope + constant.character.enum.graphql + settings + + foreground + #83c092 + + + + name + JSON grey + scope + punctuation.support.type.property-name.begin.json, punctuation.support.type.property-name.end.json, punctuation.separator.dictionary.key-value.json, punctuation.definition.string.begin.json, punctuation.definition.string.end.json, punctuation.separator.dictionary.pair.json, punctuation.separator.array.json + settings + + foreground + #859289 + + + + name + JSON orange + scope + support.type.property-name.json + settings + + foreground + #e69875 + + + + name + JSON green + scope + string.quoted.double.json + settings + + foreground + #a7c080 + + + + name + YAML grey + scope + punctuation.separator.key-value.mapping.yaml + settings + + foreground + #859289 + + + + name + YAML green + scope + string.unquoted.plain.out.yaml, string.quoted.single.yaml, string.quoted.double.yaml, punctuation.definition.string.begin.yaml, punctuation.definition.string.end.yaml, string.unquoted.plain.in.yaml, string.unquoted.block.yaml + settings + + foreground + #a7c080 + + + + name + YAML aqua + scope + punctuation.definition.anchor.yaml, punctuation.definition.block.sequence.item.yaml + settings + + foreground + #83c092 + + + + name + TOML orange + scope + keyword.key.toml + settings + + foreground + #e69875 + + + + name + TOML green + scope + string.quoted.single.basic.line.toml, string.quoted.single.literal.line.toml, punctuation.definition.keyValuePair.toml + settings + + foreground + #a7c080 + + + + name + TOML blue + scope + constant.other.boolean.toml + settings + + foreground + #7fbbb3 + + + + name + TOML purple + scope + entity.other.attribute-name.table.toml, punctuation.definition.table.toml, entity.other.attribute-name.table.array.toml, punctuation.definition.table.array.toml + settings + + foreground + #d699b6 + + + + name + Comment + scope + comment, string.comment, punctuation.definition.comment + settings + + foreground + #859289 + fontStyle + italic + + + + uuid + 3f688e48-bd62-4cd7-9981-9b491786d8c6 + colorSpaceName + sRGB + semanticClass + theme.dark.everforest-dark + author + + comment + + + diff --git a/yazi/.config/yazi/flavors/gruvbox-material.yazi/LICENSE b/yazi/.config/yazi/flavors/gruvbox-material.yazi/LICENSE new file mode 100644 index 0000000..89d0a34 --- /dev/null +++ b/yazi/.config/yazi/flavors/gruvbox-material.yazi/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 - Matthew Dong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/yazi/.config/yazi/flavors/gruvbox-material.yazi/LICENSE-tmtheme b/yazi/.config/yazi/flavors/gruvbox-material.yazi/LICENSE-tmtheme new file mode 100644 index 0000000..11069ed --- /dev/null +++ b/yazi/.config/yazi/flavors/gruvbox-material.yazi/LICENSE-tmtheme @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/yazi/.config/yazi/flavors/gruvbox-material.yazi/README.md b/yazi/.config/yazi/flavors/gruvbox-material.yazi/README.md new file mode 100644 index 0000000..ca8eadc --- /dev/null +++ b/yazi/.config/yazi/flavors/gruvbox-material.yazi/README.md @@ -0,0 +1,42 @@ +
+ Yazi logo +
+ +

+ Gruvbox Material Flavor for Yazi +

+ +## 👀 Preview + +![gruvbox-material](./preview.png) + +## 🎨 Installation + +### Using package manager + +```bash +ya pkg add matt-dong-123/gruvbox-material +``` + +### Manual install + +```bash +# Linux/macOS +git clone https://github.com/your-username/gruvbox-material.yazi.git ~/.config/yazi/flavors/gruvbox-material.yazi + +# Windows +git clone https://github.com/your-username/gruvbox-material.yazi.git %AppData%\yazi\config\flavors\gruvbox-material.yazi +``` + +## ⚙️ Usage + +Add the these lines to your `theme.toml` configuration file to use it: + +```toml +[flavor] +dark = "gruvbox-material" +``` + +## 📜 License + +Check the [LICENSE](LICENSE) file for more details. diff --git a/yazi/.config/yazi/flavors/gruvbox-material.yazi/flavor.toml b/yazi/.config/yazi/flavors/gruvbox-material.yazi/flavor.toml new file mode 100644 index 0000000..d01918c --- /dev/null +++ b/yazi/.config/yazi/flavors/gruvbox-material.yazi/flavor.toml @@ -0,0 +1,214 @@ +# vim:fileencoding=utf-8:foldmethod=marker + +# : Manager {{{ + +[mgr] +cwd = { fg = "#89b482" } + +# Find +find_keyword = { fg = "#d8a657", bold = true, italic = true, underline = true } +find_position = { fg = "#d3869b", bg = "reset", bold = true, italic = true } + +# Marker +marker_copied = { fg = "#a9b665", bg = "#a9b665" } +marker_cut = { fg = "#ea6962", bg = "#ea6962" } +marker_marked = { fg = "#89b482", bg = "#89b482" } +marker_selected = { fg = "#d8a657", bg = "#d8a657" } + +# Count +count_copied = { fg = "#282828", bg = "#a9b665" } +count_cut = { fg = "#282828", bg = "#ea6962" } +count_selected = { fg = "#282828", bg = "#d8a657" } + +# Border +border_symbol = "│" +border_style = { fg = "#928374" } + +# : }}} + + +# : Tabs {{{ + +[tabs] +active = { fg = "#282828", bg = "#7daea3", bold = true } +inactive = { fg = "#7daea3", bg = "#32302f" } + +# : }}} + + +# : Mode {{{ + +[mode] + +normal_main = { fg = "#282828", bg = "#7daea3", bold = true } +normal_alt = { fg = "#7daea3", bg = "#32302f" } + +# Select mode +select_main = { fg = "#282828", bg = "#89b482", bold = true } +select_alt = { fg = "#89b482", bg = "#32302f" } + +# Unset mode +unset_main = { fg = "#282828", bg = "#ea6962", bold = true } +unset_alt = { fg = "#ea6962", bg = "#32302f" } + +# : }}} + + +# : Status bar {{{ + +[status] +# Permissions +perm_sep = { fg = "#928374" } +perm_type = { fg = "#7daea3" } +perm_read = { fg = "#d8a657" } +perm_write = { fg = "#ea6962" } +perm_exec = { fg = "#a9b665" } + +# Progress +progress_label = { fg = "#ddc7a1", bold = true } +progress_normal = { fg = "#a9b665", bg = "#45403d" } +progress_error = { fg = "#d8a657", bg = "#ea6962" } + +# : }}} + + +# : Pick {{{ + +[pick] +border = { fg = "#7daea3" } +active = { fg = "#d3869b", bold = true } +inactive = {} + +# : }}} + + +# : Input {{{ + +[input] +border = { fg = "#7daea3" } +title = {} +value = {} +selected = { reversed = true } + +# : }}} + + +# : Completion {{{ + +[cmp] +border = { fg = "#7daea3" } + +# : }}} + + +# : Tasks {{{ + +[tasks] +border = { fg = "#7daea3" } +title = {} +hovered = { fg = "#d3869b", bold = true } + +# : }}} + + +# : Which {{{ + +[which] +mask = { bg = "#32302f" } +cand = { fg = "#89b482" } +rest = { fg = "#a89984" } +desc = { fg = "#d3869b" } +separator = "  " +separator_style = { fg = "#7c6f64" } + +# : }}} + + +# : Help {{{ + +[help] +on = { fg = "#89b482" } +run = { fg = "#d3869b" } +hovered = { reversed = true, bold = true } +footer = { fg = "#32302f", bg = "#d4be98" } + +# : }}} + + +# : Spotter {{{ + +[spot] +border = { fg = "#7daea3" } +title = { fg = "#7daea3" } +tbl_col = { fg = "#89b482" } +tbl_cell = { fg = "#d3869b", bg = "#45403d" } + +# : }}} + + +# : Notification {{{ + +[notify] +title_info = { fg = "#a9b665" } +title_warn = { fg = "#d8a657" } +title_error = { fg = "#ea6962" } + +# : }}} + + +# : File-specific styles {{{ + +[filetype] + +rules = [ + # Image + { mime = "image/*", fg = "#89b482" }, + # Media + { mime = "{audio,video}/*", fg = "#d8a657" }, + # Archive + { mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#d3869b" }, + # Document + { mime = "application/{pdf,doc,rtf}", fg = "#a9b665" }, + # Virtual file system + { mime = "vfs/{absent,stale}", fg = "#a89984" }, + # Fallback + { url = "*", fg = "#d4be98" }, + { url = "*/", fg = "#7daea3" }, +] + +# : }}} + +[icon] + +dirs = [ + { name = ".config", text = "", fg = "#d3869b" }, + { name = ".git", text = "", fg = "#89b482" }, + { name = ".github", text = "", fg = "#7daea3" }, + { name = ".npm", text = "", fg = "#7daea3" }, + { name = "Desktop", text = "", fg = "#89b482" }, + { name = "Development", text = "", fg = "#89b482" }, + { name = "Documents", text = "", fg = "#89b482" }, + { name = "Downloads", text = "", fg = "#89b482" }, + { name = "Library", text = "", fg = "#89b482" }, + { name = "Movies", text = "", fg = "#89b482" }, + { name = "Music", text = "", fg = "#89b482" }, + { name = "Pictures", text = "", fg = "#89b482" }, + { name = "Public", text = "", fg = "#89b482" }, + { name = "Videos", text = "", fg = "#89b482" }, +] +conds = [ + # Special files + { if = "orphan", text = "", fg = "#d4be98" }, + { if = "link", text = "", fg = "#928374" }, + { if = "block", text = "", fg = "#ea6962" }, + { if = "char", text = "", fg = "#ea6962" }, + { if = "fifo", text = "", fg = "#ea6962" }, + { if = "sock", text = "", fg = "#ea6962" }, + { if = "sticky", text = "", fg = "#ea6962" }, + { if = "dummy", text = "", fg = "#ea6962" }, + + # Fallback + { if = "dir", text = "", fg = "#7daea3" }, + { if = "exec", text = "", fg = "#a9b665" }, + { if = "!dir", text = "", fg = "#d4be98" }, +] \ No newline at end of file diff --git a/yazi/.config/yazi/flavors/gruvbox-material.yazi/preview.png b/yazi/.config/yazi/flavors/gruvbox-material.yazi/preview.png new file mode 100644 index 0000000..bbf67c2 Binary files /dev/null and b/yazi/.config/yazi/flavors/gruvbox-material.yazi/preview.png differ diff --git a/yazi/.config/yazi/flavors/gruvbox-material.yazi/tmtheme.xml b/yazi/.config/yazi/flavors/gruvbox-material.yazi/tmtheme.xml new file mode 100644 index 0000000..37e064d --- /dev/null +++ b/yazi/.config/yazi/flavors/gruvbox-material.yazi/tmtheme.xml @@ -0,0 +1,1376 @@ + + + + author + Matthew Dong (github.com/matt-dong-123) + colorSpaceName + sRGB + name + gruvbox-material + semanticClass + gruvbox-material + settings + + + settings + + activeGuide + #363b54 + background + #282828 + caret + #d8a657 + findHighlight + #e78a4e + findHighlightForeground + #282828 + foreground + #d4be98 + guide + #7c6f64 + gutterForeground + #928374 + inactiveSelection + #32302f + invisibles + #7c6f64 + lineHighlight + #32302f + selection + #d3869b + selectionBorder + #d3869b + shadow + #282828 + stackGuide + #7c6f64 + tagsOptions + underline + + + + name + Italics - Comments, Storage, Keyword Flow, Vue attributes, Decorators + scope + comment, meta.var.expr storage.type, keyword.control.flow, meta.directive.vue punctuation.separator.key-value.html, meta.directive.vue entity.other.attribute-name.html, tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js, storage.modifier + settings + + fontStyle + italic + + + + name + Comment + scope + comment, comment.block.documentation, punctuation.definition.comment + settings + + foreground + #928374 + + + + name + Comment Doc + scope + comment.block.documentation variable, comment.block.documentation storage, comment.block.documentation punctuation, comment.block.documentation keyword, comment.block.documentation support, comment.block.documentation markup, comment.block.documentation markup.inline.raw.string.markdown, keyword.other.phpdoc.php + settings + + foreground + #928374 + + + + name + Number, Boolean, Undefined, Null + scope + variable.other.constant, punctuation.definition.constant, constant.language, constant.numeric, support.constant + settings + + foreground + #e78a4e + + + + name + String, Symbols, Markup Heading + scope + meta.property.lua,string.unquoted.key.lua,support.other.metaproperty.lua,support.other.metaproperty.lua,constant.other.symbol, constant.other.key, markup.heading, meta.attribute-selector + settings + + fontStyle + + foreground + #89b482 + + + + name + String + scope + string + settings + + fontStyle + + foreground + #a9b665 + + + + name + Colors + scope + constant.other.color, constant.other.color.rgb-value.hex punctuation.definition.constant + settings + + foreground + #7daea3 + + + + name + Info + scope + markup.info + settings + + foreground + #89b482 + background + #32302f + + + + name + Warning + scope + markup.warning + settings + + foreground + #d8a657 + background + #45403d + + + + name + Error + scope + markup.error + settings + + foreground + #ea6962 + background + #45403d + + + + name + Invalid + scope + invalid, invalid.illegal + settings + + foreground + #ea6962 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + foreground + #d3869b + + + + name + Storage Type + scope + storage.type + settings + + foreground + #d3869b + + + + name + Storage - modifier, var, const, let + scope + meta.var.expr storage.type, storage.modifier + settings + + foreground + #d3869b + + + + name + Interpolation + scope + punctuation.definition.template-expression, punctuation.section.embedded + settings + + foreground + #7daea3 + + + + name + Spread + scope + keyword.operator.spread, keyword.operator.rest + settings + + fontStyle + bold + foreground + #ea6962 + + + + name + Operator, Misc + scope + keyword.operator, keyword.control.as, keyword.other, keyword.operator.bitwise.shift, punctuation, punctuation.definition.constant.markdown, punctuation.definition.string, punctuation.support.type.property-name, text.html.vue-html meta.tag, punctuation.definition.keyword, punctuation.terminator.rule, punctuation.definition.entity, punctuation.definition.tag, punctuation.separator.inheritance.php, punctuation.definition.tag.html, keyword.other.template, keyword.other.substitution, entity.name.operator, text.html.vue meta.tag.block.any.html, text.html.vue meta.tag.inline.any.html, text.html.vue meta.tag.other.html, text.html.twig meta.tag.inline.any.html, text.html.twig meta.tag.block.any.html, text.html.twig meta.tag.structure.any.html, text.html.twig meta.tag.any.html + settings + + foreground + #89b482 + + + + name + Import, Export, From, Default + scope + keyword.control.import, keyword.control.export, keyword.control.from, keyword.control.default, meta.import keyword.other + settings + + foreground + #7daea3 + + + + name + Keyword + scope + keyword, keyword.control, keyword.other.important + settings + + foreground + #d3869b + + + + name + Keyword SQL + scope + keyword.other.DML + settings + + foreground + #7daea3 + + + + name + Keyword Operator Logical, Arrow, Ternary, Comparison + scope + keyword.operator.logical, storage.type.function, keyword.operator.bitwise, keyword.operator.ternary, keyword.operator.comparison, keyword.operator.relational, keyword.operator.or.regexp + settings + + foreground + #d3869b + + + + name + Tag + scope + entity.name.tag, entity.name.tag support.class.component, meta.tag + settings + + foreground + #ea6962 + + + + name + Tag Punctuation + scope + punctuation.definition.tag, punctuation.definition.tag.html, punctuation.definition.tag.begin.html, punctuation.definition.tag.end.html + settings + + foreground + #d3869b + + + + name + Blade + scope + keyword.blade, entity.name.function.blade + settings + + foreground + #7daea3 + + + + name + PHP - Embedded Tag + scope + punctuation.section.embedded.begin.php, punctuation.section.embedded.end.php + settings + + foreground + #89b482 + + + + name + Smarty - Twig tag - Blade + scope + punctuation.definition.variable.smarty, punctuation.section.embedded.begin.smarty, punctuation.section.embedded.end.smarty, meta.tag.template.value.twig, punctuation.section.tag.twig, meta.tag.expression.twig, punctuation.definition.tag.expression.twig, punctuation.definition.tag.output.twig, variable.parameter.smarty + settings + + foreground + #7daea3 + + + + name + Smarty - Twig variable - function + scope + variable.other.property.twig, support.function.twig, meta.function-call.twig, keyword.control.twig, keyword.control.smarty, keyword.operator.other.twig, keyword.operator.comparison.twig, support.function.functions.twig, support.function.functions.twig, keyword.operator.assignment.twig, support.function.filters.twig, support.function.built-in.smarty, keyword.operator.smarty, text.blade text.html.blade custom.compiler.blade.php punctuation.section.embedded.php entity.name.tag.block.any.html, text.blade text.html.blade custom.compiler.blade.php punctuation.section.embedded.php constant.other.inline-data.html, text.blade text.html.blade custom.compiler.blade.php support.function constant.other.inline-data.html + settings + + foreground + #7daea3 + + + + name + Globals - PHP Constants etc + scope + constant.other.php, variable.other.global.safer, variable.other.global.safer punctuation.definition.variable, variable.other.global, variable.other.global punctuation.definition.variable, constant.other + settings + + foreground + #d8a657 + + + + name + Variables + scope + variable, support.variable, string constant.other.placeholder + settings + + foreground + #d4be98 + + + + name + Object Variable + scope + variable.other.object, support.module.node + settings + + foreground + #d4be98 + + + + name + Object Key + scope + meta.object-literal.key, meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js, string.alias.graphql, string.unquoted.graphql, string.unquoted.alias.graphql, meta.field.declaration.ts variable.object.property + settings + + foreground + #89b482 + + + + name + Object Property + scope + variable.other.property, support.variable.property, support.variable.property.dom, meta.function-call variable.other.object.property, variable.language.prototype, meta.property.object, variable.other.member + settings + + foreground + #7daea3 + + + + name + Object Property + scope + variable.other.object.property + settings + + foreground + #d4be98 + + + + name + Object Literal Member lvl 3 (Vue Prop Validation) + scope + meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.object-literal.key + settings + + foreground + #89b482 + + + + name + C-related Block Level Variables + scope + source.cpp meta.block variable.other + settings + + foreground + #ea6962 + + + + name + Other Variable + scope + support.other.variable + settings + + foreground + #ea6962 + + + + name + Methods + scope + meta.class-method.js entity.name.function.js, entity.name.method.js, variable.function.constructor, keyword.other.special-method, storage.type.cs + settings + + foreground + #7daea3 + + + + name + Function Definition + scope + entity.name.function, meta.function-call, meta.function-call entity.name.function, variable.function, meta.definition.method entity.name.function, meta.object-literal entity.name.function + settings + + foreground + #7daea3 + + + + name + Function Argument + scope + variable.parameter.function.language.special, variable.parameter, meta.function.parameters punctuation.definition.variable, meta.function.parameter variable + settings + + foreground + #d8a657 + + + + name + Constant, Tag Attribute + scope + keyword.other.type.php, storage.type.php, constant.character, constant.escape, keyword.other.unit + settings + + foreground + #d3869b + + + + name + Variable Definition + scope + meta.definition.variable variable.other.constant, meta.definition.variable variable.other.readwrite, variable.other.declaration + settings + + foreground + #d3869b + + + + name + Inherited Class + scope + entity.other.inherited-class + settings + + fontStyle + + foreground + #d3869b + + + + name + Class, Support, DOM, etc + scope + support.class, support.type, variable.other.readwrite.alias, support.orther.namespace.use.php, meta.use.php, support.other.namespace.php, support.type.sys-types, support.variable.dom, support.constant.math, support.type.object.module, support.constant.json, entity.name.namespace, meta.import.qualifier, entity.name.class + settings + + foreground + #89b482 + + + + name + Class Name + scope + entity.name + settings + + foreground + #d4be98 + + + + name + Support Function + scope + support.function + settings + + foreground + #7daea3 + + + + name + CSS Class and Support + scope + source.css support.type.property-name, source.sass support.type.property-name, source.scss support.type.property-name, source.less support.type.property-name, source.stylus support.type.property-name, source.postcss support.type.property-name, support.type.property-name.css, support.type.vendored.property-name, support.type.map.key + settings + + foreground + #7daea3 + + + + name + CSS Font + scope + support.constant.font-name, meta.definition.variable + settings + + foreground + #a9b665 + + + + name + CSS Class + scope + entity.other.attribute-name.class, meta.at-rule.mixin.scss entity.name.function.scss + settings + + foreground + #a9b665 + + + + name + CSS ID + scope + entity.other.attribute-name.id + settings + + foreground + #ea6962 + + + + name + CSS Tag + scope + entity.name.tag.css, entity.name.tag.reference, entity.name.tag.scss + settings + + foreground + #89b482 + + + + name + CSS Tag Reference + scope + entity.name.tag.reference + settings + + foreground + #d8a657 + + + + name + CSS Property Separator + scope + meta.property-list punctuation.separator.key-value + settings + + foreground + #89b482 + + + + name + CSS Punctuation + scope + meta.property-list, punctuation.definition.entity.css + settings + + foreground + #d8a657 + + + + name + SCSS @ + scope + meta.at-rule.mixin keyword.control.at-rule.mixin, meta.at-rule.include entity.name.function.scss, meta.at-rule.include keyword.control.at-rule.include + settings + + foreground + #d3869b + + + + name + SCSS Mixins, Extends, Include Keyword + scope + keyword.control.at-rule.include punctuation.definition.keyword, keyword.control.at-rule.mixin punctuation.definition.keyword, meta.at-rule.include keyword.control.at-rule.include, keyword.control.at-rule.extend punctuation.definition.keyword, meta.at-rule.extend keyword.control.at-rule.extend, entity.other.attribute-name.placeholder.css punctuation.definition.entity.css, meta.at-rule.media keyword.control.at-rule.media, meta.at-rule.mixin keyword.control.at-rule.mixin, meta.at-rule.function keyword.control.at-rule.function, keyword.control punctuation.definition.keyword, meta.at-rule.import.scss entity.other.attribute-name.placeholder.scss punctuation.definition.entity.scss, meta.at-rule.import.scss keyword.control.at-rule.import.scss + settings + + foreground + #d3869b + + + + name + SCSS Include Mixin Argument + scope + meta.property-list meta.at-rule.include + settings + + foreground + #d4be98 + + + + name + CSS value + scope + support.constant.property-value + settings + + foreground + #e78a4e + + + + name + Sub-methods + scope + entity.name.module.js, variable.import.parameter.js, variable.other.class.js + settings + + foreground + #d4be98 + + + + name + Language methods + scope + variable.language + settings + + foreground + #ea6962 + + + + name + Variable punctuation + scope + variable.other punctuation.definition.variable + settings + + foreground + #d4be98 + + + + name + Keyword this with Punctuation, ES7 Bind Operator + scope + source.js constant.other.object.key.js string.unquoted.label.js, variable.language.this punctuation.definition.variable, keyword.other.this + settings + + foreground + #ea6962 + + + + name + HTML Attributes + scope + entity.other.attribute-name, text.html.basic entity.other.attribute-name.html, text.html.basic entity.other.attribute-name, text.blade entity.other.attribute-name.class, text.html.smarty entity.other.attribute-name.class + settings + + foreground + #d3869b + + + + name + Vue Template attributes + scope + meta.directive.vue punctuation.separator.key-value.html, meta.directive.vue entity.other.attribute-name.html + settings + + foreground + #d3869b + + + + name + Vue Template attribute separator + scope + meta.directive.vue punctuation.separator.key-value.html + settings + + foreground + #89b482 + + + + name + CSS IDs + scope + source.sass keyword.control + settings + + foreground + #7daea3 + + + + name + CSS pseudo selectors + scope + entity.other.attribute-name.pseudo-class, entity.other.attribute-name.pseudo-element, entity.other.attribute-name.placeholder, meta.property-list meta.property-value + settings + + foreground + #d3869b + + + + name + Inserted + scope + markup.inserted + settings + + foreground + #a9b665 + + + + name + Deleted + scope + markup.deleted + settings + + foreground + #ea6962 + + + + name + Changed + scope + markup.changed + settings + + foreground + #7daea3 + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #89b482 + + + + name + Regular Expressions - Punctuation + scope + punctuation.definition.group + settings + + foreground + #ea6962 + + + + name + Regular Expressions - Character Class + scope + constant.other.character-class.regexp + settings + + foreground + #d3869b + + + + name + Regular Expressions - Character Class Set + scope + constant.other.character-class.set.regexp, punctuation.definition.character-class.regexp + settings + + foreground + #d8a657 + + + + name + Regular Expressions - Quantifier + scope + keyword.operator.quantifier.regexp + settings + + foreground + #89b482 + + + + name + Regular Expressions - Backslash + scope + constant.character.escape.backslash + settings + + foreground + #d4be98 + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #89b482 + + + + name + Decorators + scope + tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js + settings + + foreground + #7daea3 + + + + name + CSS Units + scope + keyword.other.unit + settings + + foreground + #ea6962 + + + + name + JSON Key - Level 0 + scope + source.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #7daea3 + + + + name + JSON Key - Level 1 + scope + source.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #89b482 + + + + name + JSON Key - Level 2 + scope + source.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #7daea3 + + + + name + JSON Key - Level 3 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #d3869b + + + + name + JSON Key - Level 4 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #d8a657 + + + + name + JSON Key - Level 5 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #89b482 + + + + name + JSON Key - Level 6 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #89b482 + + + + name + JSON Key - Level 7 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json + settings + + foreground + #ea6962 + + + + name + JSON Key - Level 8 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json punctuation.definition.string.end.json + settings + + foreground + #a9b665 + + + + name + JSON Key - value + scope + source.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #a9b665 + + + + name + Plain Punctuation + scope + punctuation.definition.list_item.markdown + settings + + foreground + #89b482 + + + + name + Block Punctuation + scope + meta.block, meta.brace, punctuation.definition.block, punctuation.definition.use, punctuation.definition.group.shell, punctuation.definition.class, punctuation.definition.begin.bracket, punctuation.definition.end.bracket, punctuation.definition.parameters, punctuation.definition.arguments, punctuation.definition.dictionary, punctuation.definition.array, punctuation.section + settings + + foreground + #89b482 + + + + name + Markdown - Plain + scope + meta.jsx.children, meta.embedded.block + settings + + foreground + #d4be98 + + + + name + HTML text + scope + text.html + settings + + foreground + #7daea3 + + + + name + Markdown - Markup Raw Inline + scope + text.html.markdown markup.inline.raw.markdown + settings + + foreground + #d3869b + + + + name + Markdown - Markup Raw Inline Punctuation + scope + text.html.markdown markup.inline.raw.markdown punctuation.definition.raw.markdown + settings + + foreground + #7c6f64 + + + + name + Markdown - Heading 1 + scope + heading.1.markdown entity.name, heading.1.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #89b482 + + + + name + Markdown - Heading 2 + scope + heading.2.markdown entity.name, heading.2.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #89b482 + + + + name + Markdown - Heading 3 + scope + heading.3.markdown entity.name, heading.3.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #7daea3 + + + + name + Markdown - Heading 4 + scope + heading.4.markdown entity.name, heading.4.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #7daea3 + + + + name + Markdown - Heading 5 + scope + heading.5.markdown entity.name, heading.5.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #7daea3 + + + + name + Markdown - Heading 6 + scope + heading.6.markdown entity.name, heading.6.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #a89984 + + + + name + Markup - Italic + scope + markup.italic, markup.italic punctuation + settings + + fontStyle + italic + foreground + #d4be98 + + + + name + Markup - Bold + scope + markup.bold, markup.bold punctuation + settings + + fontStyle + bold + foreground + #d4be98 + + + + name + Markup - Bold-Italic + scope + markup.bold markup.italic, markup.bold markup.italic punctuation + settings + + fontStyle + bold italic + foreground + #d4be98 + + + + name + Markup - Underline + scope + markup.underline, markup.underline punctuation + settings + + fontStyle + underline + + + + name + Markdown - Blockquote + scope + markup.quote punctuation.definition.blockquote.markdown + settings + + foreground + #7c6f64 + + + + name + Markup - Quote + scope + markup.quote + settings + + fontStyle + italic + + + + name + Markdown - Link + scope + string.other.link, markup.underline.link, constant.other.reference.link.markdown, string.other.link.description.title.markdown + settings + + foreground + #89b482 + + + + name + Markdown - Fenced Code Block + scope + markup.fenced_code.block.markdown, markup.inline.raw.string.markdown, variable.language.fenced.markdown + settings + + foreground + #89b482 + + + + name + Markdown - Separator + scope + meta.separator + settings + + fontStyle + bold + foreground + #7c6f64 + + + + name + Markup - Table + scope + markup.table + settings + + foreground + #d4be98 + + + + name + Token - Info + scope + token.info-token + settings + + foreground + #89b482 + + + + name + Token - Warn + scope + token.warn-token + settings + + foreground + #d8a657 + + + + name + Token - Error + scope + token.error-token + settings + + foreground + #ea6962 + + + + name + Token - Debug + scope + token.debug-token + settings + + foreground + #d3869b + + + + name + Apache Tag + scope + entity.tag.apacheconf + settings + + foreground + #ea6962 + + + + name + Preprocessor + scope + meta.preprocessor + settings + + foreground + #89b482 + + + + name + ENV value + scope + source.env + settings + + foreground + #7daea3 + + + + uuid + 06f855e3-9fb7-4fb1-b790-aef06065f34e + + diff --git a/yazi/.config/yazi/flavors/kanagawa.yazi/LICENSE b/yazi/.config/yazi/flavors/kanagawa.yazi/LICENSE new file mode 100644 index 0000000..1b1dfdc --- /dev/null +++ b/yazi/.config/yazi/flavors/kanagawa.yazi/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Dmitry Nefedov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/yazi/.config/yazi/flavors/kanagawa.yazi/LICENSE-tmtheme b/yazi/.config/yazi/flavors/kanagawa.yazi/LICENSE-tmtheme new file mode 100644 index 0000000..1b1dfdc --- /dev/null +++ b/yazi/.config/yazi/flavors/kanagawa.yazi/LICENSE-tmtheme @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Dmitry Nefedov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/yazi/.config/yazi/flavors/kanagawa.yazi/README.md b/yazi/.config/yazi/flavors/kanagawa.yazi/README.md new file mode 100644 index 0000000..d314236 --- /dev/null +++ b/yazi/.config/yazi/flavors/kanagawa.yazi/README.md @@ -0,0 +1,36 @@ +
+ Yazi logo +
+ +

+ Kanagawa Flavor for Yazi +

+ +## 👀 Preview + + + +## 🎨 Installation + +```bash +ya pkg add dangooddd/kanagawa +``` + +## ⚙️ Usage + +> [!Note] +> To achieve the look like in the screenshot you also need to install +> [full-border](https://github.com/yazi-rs/plugins/tree/main/full-border.yazi) plugin! + +Add these lines to your `theme.toml` configuration file to use it: + +```toml +[flavor] +dark = "kanagawa" +``` + +## 📜 License + +The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed. + +Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details. diff --git a/yazi/.config/yazi/flavors/kanagawa.yazi/flavor.toml b/yazi/.config/yazi/flavors/kanagawa.yazi/flavor.toml new file mode 100644 index 0000000..7703335 --- /dev/null +++ b/yazi/.config/yazi/flavors/kanagawa.yazi/flavor.toml @@ -0,0 +1,143 @@ +## Color palette +## Check https://github.com/rebelot/kanagawa.nvim for more details +# sumiInk0 "#16161d" dark bg +# sumiInk3 "#1f1f28" bg +# sumiInk4 "#2a2a37" +# sumiInk6 "#54546d" +# fujiWhite "#dcd7ba" fg +# oldWhite "#c8c093" dark fg +# fujiGray "#727169" +# peachRed "#ff5d62" +# autumnRed "#c34043" +# crystalBlue "#7e9cd8" +# waveRed "#e46876" +# carpYellow "#e6c384" +# springGreen "#98bb6c" +# autumnGreen "#76946a" +# oniViolet "#957fb8" +# waveAqua1 "#6a9589" +# surimiOrange "#ffa066" +# waveAqua2 "#7aa89f" + +[mgr] +marker_copied = { fg = "#98bb6c", bg = "#98bb6c" } +marker_cut = { fg = "#e46876", bg = "#e46876" } +marker_marked = { fg = "#957fb8", bg = "#957fb8" } +marker_selected = { fg = "#ffa066", bg = "#ffa066" } + +cwd = { fg = "#e6c384" } + +find_keyword = { fg = "#ffa066", bg = "#1f1f28" } +find_position = {} + +count_copied = { fg = "#1f1f28", bg = "#98bb6c" } +count_cut = { fg = "#1f1f28", bg = "#e46876" } +count_selected = { fg = "#1f1f28", bg = "#ffa066" } + +border_symbol = "│" +border_style = { fg = "#dcd7ba" } + +[indicator] +parent = { reversed = true } +current = { reversed = true } +preview = { reversed = true } + +[tabs] +active = { fg = "#1f1f28", bg = "#7e9cd8" } +inactive = { fg = "#7e9cd8", bg = "#2a2a37" } + +sep_inner = { open = "", close = "" } +sep_outer = { open = "", close = "" } + + +[mode] +normal_main = { fg = "#1f1f28", bg = "#7e9cd8" } +normal_alt = { fg = "#7e9cd8", bg = "#2a2a37" } +select_main = { fg = "#1f1f28", bg = "#957fb8" } +select_alt = { fg = "#957fb8", bg = "#2a2a37" } +unset_main = { fg = "#1f1f28", bg = "#e6c384" } +unset_alt = { fg = "#e6c384", bg = "#2a2a37" } + + +[status] +sep_left = { open = "", close = "" } +sep_right = { open = "", close = "" } +overall = { fg = "#c8c093", bg = "#16161d" } + +progress_label = { fg = "#7e9cd8", bold = true } +progress_normal = { fg = "#2a2a37", bg = "#1f1f28" } +progress_error = { fg = "#2a2a37", bg = "#1f1f28" } + +perm_type = { fg = "#98bb6c" } +perm_read = { fg = "#e6c384" } +perm_write = { fg = "#ff5d62" } +perm_exec = { fg = "#7aa89f" } +perm_sep = { fg = "#957fb8" } + + +[pick] +border = { fg = "#7fb4ca" } +active = { fg = "#957fb8", bold = true } +inactive = {} + +[input] +border = { fg = "#7fb4ca" } +title = {} +value = {} +selected = { reversed = true } + +[completion] +border = { fg = "#7fb4ca" } +active = { reversed = true } +inactive = {} + +[tasks] +border = { fg = "#7fb4ca" } +title = {} +hovered = { fg = "#957fb8" } + +[which] +cols = 2 +separator = " - " +separator_style = { fg = "#727169" } +mask = { bg = "#16161d" } +rest = { fg = "#727169" } +cand = { fg = "#7e9cd8" } +desc = { fg = "#54546d" } + +[help] +on = { fg = "#7aa89f" } +run = { fg = "#957fb8" } +desc = {} +hovered = { reversed = true, bold = true } +footer = { fg = "#1f1f28", bg = "#dcd7ba" } + +[notify] +title_info = { fg = "#98bb6c" } +title_warn = { fg = "#e6c384" } +title_error = { fg = "#ff5d62" } + +[filetype] +rules = [ + # images + { mime = "image/*", fg = "#e6c384" }, + + # media + { mime = "{audio,video}/*", fg = "#957fb8" }, + + # archives + { mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#e46876" }, + + # documents + { mime = "application/{pdf,doc,rtf,vnd.*}", fg = "#6a9589" }, + + # broken links + { url = "*", is = "orphan", fg = "#c34043" }, + + # executables + { url = "*", is = "exec", fg = "#76946a" }, + + # fallback + { url = "*", fg = "#dcd7ba" }, + { url = "*/", fg = "#7e9cd8" }, +] diff --git a/yazi/.config/yazi/flavors/kanagawa.yazi/preview.png b/yazi/.config/yazi/flavors/kanagawa.yazi/preview.png new file mode 100644 index 0000000..87d0767 Binary files /dev/null and b/yazi/.config/yazi/flavors/kanagawa.yazi/preview.png differ diff --git a/yazi/.config/yazi/flavors/kanagawa.yazi/tmtheme.xml b/yazi/.config/yazi/flavors/kanagawa.yazi/tmtheme.xml new file mode 100644 index 0000000..737e459 --- /dev/null +++ b/yazi/.config/yazi/flavors/kanagawa.yazi/tmtheme.xml @@ -0,0 +1,448 @@ + + + + + name + Kanagawa + settings + + + settings + + background + #1F1F28 + caret + #C8C093 + foreground + #DCD7BA + invisibles + #54546D + lineHighlight + #2D4F67 + selection + #2D4F67 + findHighlight + #2D4F67 + selectionBorder + #222218 + gutterForeground + #54546D + + + + name + Comment + scope + comment + settings + + foreground + #727169 + + + + name + String + scope + string + settings + + foreground + #98BB6C + + + + name + Number + scope + constant.numeric + settings + + foreground + #D27E99 + + + + name + Built-in constant + scope + constant.language + settings + + foreground + #FFA066 + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #E6C384 + + + + name + Variable + scope + variable + settings + + fontStyle + #E6C384 + + + + name + Ruby's @variable + scope + variable.other.readwrite.instance + settings + + fontStyle + + foreground + #E6C384 + + + + name + String interpolation + scope + constant.character.escaped, constant.character.escape, string source, string source.ruby + settings + + fontStyle + + foreground + #C0A36E + + + + name + Keyword + scope + keyword + settings + + foreground + #E46876 + + + + name + Storage + scope + storage + settings + + fontStyle + + foreground + #957FB8 + + + + name + Storage type + scope + storage.type + settings + + foreground + #957FB8 + + + + name + Class name + scope + entity.name.class + settings + + foreground + #7AA89F + + + + name + Inherited class + scope + entity.other.inherited-class + settings + + foreground + #7AA89F + + + + name + Function name + scope + entity.name.function + settings + + fontStyle + + foreground + #7E9CD8 + + + + name + Function argument + scope + variable.parameter + settings + + foreground + #b8b4d0 + + + + name + Tag name + scope + entity.name.tag + settings + + fontStyle + + foreground + #7FB4CA + + + + name + Tag attribute + scope + entity.other.attribute-name + settings + + fontStyle + + foreground + #E6C384 + + + + name + Library function + scope + support.function + settings + + fontStyle + + foreground + #7FB4CA + + + + name + Library constant + scope + support.constant + settings + + fontStyle + + foreground + #7FB4CA + + + + name + Library class/type + scope + support.type, support.class + settings + + foreground + #7AA89F + + + + name + Library variable + scope + support.other.variable + settings + + foreground + #FFA066 + + + + name + Invalid + scope + invalid + settings + + fontStyle + + foreground + #FF5D62 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + foreground + #717C7C + + + + name + JSON String + scope + meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #957FB8 + + + + name + diff.header + scope + meta.diff, meta.diff.header + settings + + foreground + #7E9CD8 + + + + name + diff.deleted + scope + markup.deleted + settings + + background + #43242B + + + + name + diff.inserted + scope + markup.inserted + settings + + background + #2B3328 + + + + name + diff.changed + scope + markup.changed + settings + + background + #49443C + + + + scope + constant.numeric.line-number.find-in-files - match + settings + + foreground + #54546D + + + + scope + entity.name.filename + settings + + foreground + #C8C093 + + + + scope + message.error + settings + + foreground + #E82424 + + + + name + JSON Punctuation + scope + punctuation.definition.string.begin.json - meta.structure.dictionary.value.json, punctuation.definition.string.end.json - meta.structure.dictionary.value.json + settings + + foreground + #9CABCA + + + + name + JSON Structure + scope + meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #957FB8 + + + + name + JSON String + scope + meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #ffffff + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #FF5D62 + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #E6C384 + + + + uuid + 592FC036-6BB7-4676-A2F5-2894D48C8E33 + colorSpaceName + sRGB + semanticClass + theme.dark.kanagawa + + diff --git a/yazi/.config/yazi/flavors/monokai.yazi/LICENSE b/yazi/.config/yazi/flavors/monokai.yazi/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/yazi/.config/yazi/flavors/monokai.yazi/LICENSE-tmtheme b/yazi/.config/yazi/flavors/monokai.yazi/LICENSE-tmtheme new file mode 100644 index 0000000..e69de29 diff --git a/yazi/.config/yazi/flavors/monokai.yazi/README.md b/yazi/.config/yazi/flavors/monokai.yazi/README.md new file mode 100644 index 0000000..6303635 --- /dev/null +++ b/yazi/.config/yazi/flavors/monokai.yazi/README.md @@ -0,0 +1,37 @@ +
+ Yazi logo +
+ +

+ Monokai flavor for Yazi +

+ +## 👀 Preview + + + +## 🎨 Installation + + +```sh +ya pkg add malick-tammal/monokai +``` + +## ⚙️ Usage + +Add it to your `theme.toml` as dark flavor: + +```toml +[flavor] +dark = "monokai" +``` + +Make sure your `theme.toml` doesn't contain anything other than `[flavor]`, unless you want to override certain styles of this flavor. + +See the [Yazi flavor documentation](https://yazi-rs.github.io/docs/flavors/overview) for more details. + +## 📜 License + +The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed. + +Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details. diff --git a/yazi/.config/yazi/flavors/monokai.yazi/flavor.toml b/yazi/.config/yazi/flavors/monokai.yazi/flavor.toml new file mode 100644 index 0000000..fab2a95 --- /dev/null +++ b/yazi/.config/yazi/flavors/monokai.yazi/flavor.toml @@ -0,0 +1,182 @@ +#---------------------------------------------------------- +#-- HACK: Monokai +#---------------------------------------------------------- + +[mgr] +cwd = { fg = "#78DCE8" } + +# Hovered +hovered = { reversed = true } +preview_hovered = { underline = true } + +# Find +find_symbol = " Finding: " +find_keyword = { fg = "#FF6188", bold = true, italic = true, underline = true } +find_position = { fg = "#AB9DF2", bg = "reset", bold = true, italic = true } + +# Symlink +symlink_target = { fg = "#78DCE8", italic = true } + +# Marker +marker_copied = { fg = "#A9DC76", bg = "#A9DC76" } +marker_cut = { fg = "lightred", bg = "lightred" } +marker_marked = { fg = "#AB9DF2", bg = "#AB9DF2" } +marker_selected = { fg = "#FF6188", bg = "#FF6188" } + +# Count +count_copied = { fg = "#221F22", bg = "#A9DC76" } +count_cut = { fg = "#221F22", bg = "#FF6188" } +count_selected = { fg = "#221F22", bg = "#FFD866" } + +# Border +border_symbol = "│" +border_style = { fg = "#727072" } + +# Tabs +[tabs] +active = { fg = "#221F22", bg = "#FFD866", bold = true } +inactive = { fg = "#FFD866", bg = "#221F22" } + +# Separator +sep_inner = { open = "", close = "" } +sep_outer = { open = "", close = "" } + +# Modes +[mode] +# Normal mode +normal_main = { fg = "#2D2A2E", bg = "#FFD866", bold = true } +normal_alt = { fg = "#FFD866", bg = "#403E41" } + +# Select mode +select_main = { fg = "#2D2A2E", bg = "#AB9DF2", bold = true } +select_alt = { fg = "#AB9DF2", bg = "#403E41" } + +# Unset mode +unset_main = { bg = "#FF6188", bold = true } +unset_alt = { fg = "#FF6188", bg = "gray" } + +# Status bar +[status] +overall = {} +sep_left = { open = "", close = "" } +sep_right = { open = "", close = "" } + +# Permissions +perm_sep = { fg = "#727072" } +perm_type = { fg = "#A9DC76" } +perm_read = { fg = "#FFD866" } +perm_write = { fg = "#FF6188" } +perm_exec = { fg = "#78DCE8" } + +# Progress +progress_label = { bold = true } +progress_normal = { fg = "#78DCE8", bg = "#2D2A2E" } +progress_error = { fg = "#FF6188", bg = "#2D2A2E" } + +# Which +[which] +cols = 3 +mask = { bg = "#2D2A2E" } +cand = { fg = "lightcyan" } +rest = { fg = "#727072" } +desc = { fg = "lightmagenta" } +separator = "  " +separator_style = { fg = "#727072" } + +# Confirmation +[confirm] +border = { fg = "#FFD866" } +title = { fg = "#FFD866" } +content = {} +list = {} +btn_yes = { reversed = true } +btn_no = {} +btn_labels = [" [Y]es ", " (N)o "] + +# Spotter +[spot] +border = { fg = "#78DCE8" } +title = { fg = "#78DCE8" } + +# Table +tbl_col = { fg = "#78DCE8" } +tbl_cell = { fg = "#FFD866", reversed = true } + +# Norifications +[notify] +title_info = { fg = "#A9DC76" } +title_warn = { fg = "#FFD866" } +title_error = { fg = "#FF6188" } + +# Icons +icon_info = "" +icon_warn = "" +icon_error = "" + +# Picker +[pick] +border = { fg = "#78DCE8" } +active = { fg = "#AB9DF2", bold = true } +inactive = {} + +# Input +[input] +border = { fg = "#78DCE8" } +title = {} +value = {} +selected = { reversed = true } + +# Completion +[cmp] +border = { fg = "#78DCE8" } +active = { reversed = true } +inactive = {} + +# Icons +icon_file = "" +icon_folder = "" +icon_command = "" + +# : Task manager {{{ +[tasks] +border = { fg = "#78DCE8" } +title = {} +hovered = { fg = "#AB9DF2", underline = true } + +# Help menu +[help] +on = { fg = "#78DCE8" } +run = { fg = "#AB9DF2" } +desc = {} +hovered = { reversed = true, bold = true } +footer = { fg = "#221F22", bg = "#FDFFF1" } + +# File-specific styles +[filetype] +rules = [ + # Images + { mime = "image/*", fg = "#FFD866" }, + + # Media + { mime = "{audio,video}/*", fg = "#A9DC76" }, + + # Archives + { mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#FF6188" }, + + # Documents + { mime = "application/{pdf,doc,rtf}", fg = "#78DCE8" }, + + # Empty files + { mime = "inode/empty", fg = "#FF6188" }, + + # Special files + { url = "*", is = "orphan", bg = "#FF6188" }, + { url = "*", is = "exec", fg = "#A9DC76" }, + + # Dummy files + { url = "*", is = "dummy", bg = "#FF6188" }, + { url = "*/", is = "dummy", bg = "#FF6188" }, + + # Fallback + { url = "*/", fg = "#FC9767", bold = true }, +] diff --git a/yazi/.config/yazi/flavors/monokai.yazi/preview.png b/yazi/.config/yazi/flavors/monokai.yazi/preview.png new file mode 100644 index 0000000..5b71ba8 Binary files /dev/null and b/yazi/.config/yazi/flavors/monokai.yazi/preview.png differ diff --git a/yazi/.config/yazi/flavors/monokai.yazi/tmtheme.xml b/yazi/.config/yazi/flavors/monokai.yazi/tmtheme.xml new file mode 100644 index 0000000..fbf090b --- /dev/null +++ b/yazi/.config/yazi/flavors/monokai.yazi/tmtheme.xml @@ -0,0 +1,300 @@ + + + + + gutterSettings + + background + #49483E + divider + #75715E + foreground + #75715E + + name + Monokai + semanticClass + theme.dark.monokai + settings + + + settings + + background + #272822 + caret + #F8F8F0 + foreground + #F8F8F2 + invisibles + #49483E + lineHighlight + #49483E + selection + #49483E + + + + name + Comment + scope + comment + settings + + foreground + #75715E + + + + name + String + scope + string + settings + + foreground + #E6DB74 + + + + name + Number + scope + constant.numeric + settings + + foreground + #AE81FF + + + + name + Built-in constant + scope + constant.language + settings + + foreground + #AE81FF + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #AE81FF + + + + name + Variable + scope + variable + settings + + fontStyle + + + + + name + Keyword + scope + keyword + settings + + foreground + #F92672 + + + + name + Storage + scope + storage + settings + + fontStyle + + foreground + #F92672 + + + + name + Storage type + scope + storage.type + settings + + fontStyle + italic + foreground + #66D9EF + + + + name + Class name + scope + entity.name.class + settings + + fontStyle + underline + foreground + #A6E22E + + + + name + Inherited class + scope + entity.other.inherited-class + settings + + fontStyle + italic underline + foreground + #A6E22E + + + + name + Function name + scope + entity.name.function + settings + + fontStyle + + foreground + #A6E22E + + + + name + Function argument + scope + variable.parameter + settings + + fontStyle + italic + foreground + #FD971F + + + + name + Tag name + scope + entity.name.tag + settings + + fontStyle + + foreground + #F92672 + + + + name + Tag attribute + scope + entity.other.attribute-name + settings + + fontStyle + + foreground + #A6E22E + + + + name + Library function + scope + support.function + settings + + fontStyle + + foreground + #66D9EF + + + + name + Library constant + scope + support.constant + settings + + fontStyle + + foreground + #66D9EF + + + + name + Library class/type + scope + support.type, support.class + settings + + fontStyle + italic + foreground + #66D9EF + + + + name + Library variable + scope + support.other.variable + settings + + fontStyle + + + + + name + Invalid + scope + invalid + settings + + background + #F92672 + fontStyle + + foreground + #F8F8F0 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + background + #AE81FF + foreground + #F8F8F0 + + + + uuid + D8D5E82E-3D5B-46B5-B38E-8C841C21347D + + diff --git a/yazi/.config/yazi/flavors/tokyo-night.yazi/LICENSE b/yazi/.config/yazi/flavors/tokyo-night.yazi/LICENSE new file mode 100644 index 0000000..9a5124e --- /dev/null +++ b/yazi/.config/yazi/flavors/tokyo-night.yazi/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 - sxyazi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/yazi/.config/yazi/flavors/tokyo-night.yazi/LICENSE-tmtheme b/yazi/.config/yazi/flavors/tokyo-night.yazi/LICENSE-tmtheme new file mode 100644 index 0000000..44b4479 --- /dev/null +++ b/yazi/.config/yazi/flavors/tokyo-night.yazi/LICENSE-tmtheme @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Himanshu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/yazi/.config/yazi/flavors/tokyo-night.yazi/README.md b/yazi/.config/yazi/flavors/tokyo-night.yazi/README.md new file mode 100644 index 0000000..70eb613 --- /dev/null +++ b/yazi/.config/yazi/flavors/tokyo-night.yazi/README.md @@ -0,0 +1,47 @@ +
+ Yazi logo +
+ +

+ Tokyo Night Flavor for Yazi +

+ +## 👀 Preview + + + +## 🎨 Installation + +### Using package manager + +```bash +ya pkg add BennyOe/tokyo-night +``` + +### Manual install + +```bash +# Linux/macOS +git clone https://github.com/BennyOe/tokyo-night.yazi.git ~/.config/yazi/flavors/tokyo-night.yazi + +# Windows +git clone https://github.com/BennyOe/tokyo-night.yazi.git %AppData%\yazi\config\flavors\tokyo-night.yazi +``` + +## ⚙️ Usage + +Add the these lines to your `theme.toml` configuration file to use it: + + +```toml +[flavor] +use = "tokyo-night" +# For Yazi 0.4 and above +dark = "tokyo-night" +``` + +## 📜 License + +The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed. + +Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details. diff --git a/yazi/.config/yazi/flavors/tokyo-night.yazi/flavor.toml b/yazi/.config/yazi/flavors/tokyo-night.yazi/flavor.toml new file mode 100644 index 0000000..9f008c6 --- /dev/null +++ b/yazi/.config/yazi/flavors/tokyo-night.yazi/flavor.toml @@ -0,0 +1,201 @@ +# vim:fileencoding=utf-8:foldmethod=marker + +# : Manager {{{ + +[mgr] +cwd = { fg = "#7aa2f7" } + +# Find +find_keyword = { fg = "#f7768e", bold = true, italic = true, underline = true } +find_position = { fg = "#bb9af7", bg = "reset", bold = true, italic = true } + +# Marker +marker_copied = { fg = "#9ece6a", bg = "#9ece6a" } +marker_cut = { fg = "#e0af68", bg = "#f7768e" } +marker_marked = { fg = "#7aa2f7", bg = "#7dcfff" } +marker_selected = { fg = "#e0af68", bg = "#e0af68" } + +# Count +count_copied = { fg = "#1a1b26", bg = "#9ece6a" } +count_cut = { fg = "#1a1b26", bg = "#e0af68" } +count_selected = { fg = "#1a1b26", bg = "#7aa2f7" } + +# Border +border_symbol = "│" +border_style = { fg = "#414868" } + +# : }}} + + +# : Tabs {{{ + +[tabs] +active = { fg = "#292e42", bg = "#7aa2f7", bold = true } +inactive = { fg = "#7aa2f7", bg = "#292e42" } + +# : }}} + + +# : Mode {{{ + +[mode] + +normal_main = { fg = "#292e42", bg = "#7aa2f7", bold = true } +normal_alt = { fg = "#7aa2f7", bg = "#292e42" } + +# Select mode +select_main = { fg = "#292e42", bg = "#9ece6a", bold = true } +select_alt = { fg = "#7aa2f7", bg = "#292e42" } + +# Unset mode +unset_main = { fg = "#292e42", bg = "#bb9af7", bold = true } +unset_alt = { fg = "#7aa2f7", bg = "#292e42" } + +# : }}} + + +# : Status bar {{{ + +[status] +overall = { fg = "#7aa2f7" } +sep_left = { open = "", close = "" } +sep_right = { open = "", close = "" } + + +# Progress +progress_label = { fg = "#292e42", bold = true } +progress_normal = { fg = "#7aa2f7", bg = "#292e42" } +progress_error = { fg = "#f7768e", bg = "#292e42" } + +# Permissions +perm_sep = { fg = "#7aa2f7" } +perm_type = { fg = "#9ece6a" } +perm_read = { fg = "#e0af68" } +perm_write = { fg = "#f7768e" } +perm_exec = { fg = "#bb9af7" } + + +# : }}} + +# : Pick {{{ + +[pick] +border = { fg = "#7aa2f7" } +active = { fg = "#bb9af7", bold = true } +inactive = {} + +# : }}} + + +# : Input {{{ + +[input] +border = { fg = "#7aa2f7" } +title = {} +value = {} +selected = { reversed = true } + +# : }}} + + +# : Completion {{{ + +[cmp] +border = { fg = "#7aa2f7" } + +# : }}} + + +# : Tasks {{{ + +[tasks] +border = { fg = "#7aa2f7" } +title = {} +hovered = { fg = "#bb9af7", underline = true } + +# : }}} + + +# : Which {{{ + +[which] +mask = { bg = "#414868" } +cand = { fg = "#9ece6a" } +rest = { fg = "#a9b1d6" } +desc = { fg = "#bb9af7" } +separator = "  " +separator_style = { fg = "#626880" } + +# : }}} + + +# : Help {{{ + +[help] +on = { fg = "#9ece6a" } +run = { fg = "#bb9af7" } +hovered = { reversed = true, bold = true } +footer = { fg = "#1a1b26", bg = "#a9b1d6" } + +# : }}} + + +# : Spotter {{{ + +[spot] +border = { fg = "#7aa2f7" } +title = { fg = "#7aa2f7" } +tbl_col = { fg = "#9ece6a" } +tbl_cell = { fg = "#bb9af7", bg = "#292e42" } + +# : }}} + + +# : Notify {{{ + +[notify] +title_info = { fg = "#9ece6a" } +title_warn = { fg = "#f7768e" } +title_error = { fg = "#e0af68" } + +# : }}} + + +# : File-specific styles {{{ + +[filetype] + +rules = [ + # Images + { mime = "image/*", fg = "#e0af68" }, + + # Media + { mime = "video/*", fg = "#f7768e" }, + { mime = "audio/*", fg = "#f7768e" }, + + # Archives + { mime = "application/zip", fg = "#bb9af7" }, + { mime = "application/x-tar", fg = "#bb9af7" }, + { mime = "application/x-bzip*", fg = "#bb9af7" }, + { mime = "application/x-bzip2", fg = "#bb9af7" }, + { mime = "application/x-7z-compressed", fg = "#bb9af7" }, + { mime = "application/x-rar", fg = "#bb9af7" }, + { mime = "application/x-xz", fg = "#bb9af7" }, + + # Documents + { mime = "application/doc", fg = "#9ece6a" }, + { mime = "application/epub+zip", fg = "#9ece6a" }, + { mime = "application/pdf", fg = "#9ece6a" }, + { mime = "application/rtf", fg = "#9ece6a" }, + { mime = "application/vnd.*", fg = "#9ece6a" }, + + # Special files + { mime = "*", is = "orphan", fg = "#f29cb4", bg = "#93000a" }, + { mime = "application/*exec*", fg = "#f7768e" }, + + # Fallback + { url = "*", fg = "#c6d0f5" }, + { url = "*/", fg = "#7aa2f7" }, +] + +# : }}} diff --git a/yazi/.config/yazi/flavors/tokyo-night.yazi/preview.png b/yazi/.config/yazi/flavors/tokyo-night.yazi/preview.png new file mode 100644 index 0000000..75f2f4a Binary files /dev/null and b/yazi/.config/yazi/flavors/tokyo-night.yazi/preview.png differ diff --git a/yazi/.config/yazi/flavors/tokyo-night.yazi/tmtheme.xml b/yazi/.config/yazi/flavors/tokyo-night.yazi/tmtheme.xml new file mode 100644 index 0000000..21d2163 --- /dev/null +++ b/yazi/.config/yazi/flavors/tokyo-night.yazi/tmtheme.xml @@ -0,0 +1,1329 @@ + + + + + author + Kristi Russell (http://github.com/enkia) + colorSpaceName + sRGB + name + Enki-Tokyo-Night + semanticClass + enki.theme.tokyo + settings + + + settings + + activeGuide + #363b54 + background + #1d1f29 + caret + #DBC08A + findHighlight + #ffa300 + findHighlightForeground + #000000 + foreground + #AFBAD4ff + guide + #4f4f5e40 + gutterForeground + #3b415caa + inactiveSelection + #282833 + invisibles + #4f4f5e + lineHighlight + #00000030 + phantomCss + <![CDATA[ html { position: relative; } ]]> + popupCss + <![CDATA[ html { color: #B376B3; background-color: #2b2d3a; padding: 10px; } a { color: #6189BB; line-height: 1.2; text-decoration: none; } .error, .deleted { color: #50B4DC; } .success, .inserted { color: #9DBA72; } .warning, .modified { color: #ffa300; } ]]> + selection + #9D599D40 + selectionBorder + #9D599D + shadow + #00000010 + stackGuide + #4f4f5e60 + tagsOptions + underline + + + + name + Italics - Comments, Storage, Keyword Flow, Vue attributes, Decorators + scope + comment, meta.var.expr storage.type, keyword.control.flow, meta.directive.vue punctuation.separator.key-value.html, meta.directive.vue entity.other.attribute-name.html, tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js, storage.modifier + settings + + fontStyle + italic + + + + name + Comment + scope + comment, comment.block.documentation, punctuation.definition.comment + settings + + foreground + #444b6a + + + + name + Comment Doc + scope + comment.block.documentation variable, comment.block.documentation storage, comment.block.documentation punctuation, comment.block.documentation keyword, comment.block.documentation support, comment.block.documentation markup, comment.block.documentation markup.inline.raw.string.markdown, keyword.other.phpdoc.php + settings + + foreground + #7982a9 + + + + name + Number, Boolean, Undefined, Null + scope + variable.other.constant, punctuation.definition.constant, constant.language, constant.numeric, support.constant + settings + + foreground + #ff9e64 + + + + name + String, Symbols, Markup Heading + scope + string, constant.other.symbol, constant.other.key, markup.heading, meta.attribute-selector + settings + + fontStyle + + foreground + #9ece6a + + + + name + Colors + scope + constant.other.color, constant.other.color.rgb-value.hex punctuation.definition.constant + settings + + foreground + #9aa5ce + + + + name + Invalid + scope + invalid, invalid.illegal + settings + + foreground + #ff5370 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + foreground + #bb9af7 + + + + name + Storage Type + scope + storage.type + settings + + foreground + #bb9af7 + + + + name + Storage - modifier, var, const, let + scope + meta.var.expr storage.type, storage.modifier + settings + + foreground + #9d7cd8 + + + + name + Interpolation + scope + punctuation.definition.template-expression, punctuation.section.embedded + settings + + foreground + #7dcfff + + + + name + Spread + scope + keyword.operator.spread, keyword.operator.rest + settings + + fontStyle + bold + foreground + #f7768e + + + + name + Operator, Misc + scope + keyword.operator, keyword.control.as, keyword.other, keyword.operator.bitwise.shift, punctuation, punctuation.definition.constant.markdown, punctuation.definition.string, punctuation.support.type.property-name, text.html.vue-html meta.tag, punctuation.definition.keyword, punctuation.terminator.rule, punctuation.definition.entity, punctuation.definition.tag, punctuation.separator.inheritance.php, punctuation.definition.tag.html, keyword.other.template, keyword.other.substitution, entity.name.operator, text.html.vue meta.tag.block.any.html, text.html.vue meta.tag.inline.any.html, text.html.vue meta.tag.other.html, text.html.twig meta.tag.inline.any.html, text.html.twig meta.tag.block.any.html, text.html.twig meta.tag.structure.any.html, text.html.twig meta.tag.any.html + settings + + foreground + #89ddff + + + + name + Import, Export, From, Default + scope + keyword.control.import, keyword.control.export, keyword.control.from, keyword.control.default, meta.import keyword.other + settings + + foreground + #7dcfff + + + + name + Keyword + scope + keyword, keyword.control, keyword.other.important + settings + + foreground + #bb9af7 + + + + name + Keyword SQL + scope + keyword.other.DML + settings + + foreground + #7dcfff + + + + name + Keyword Operator Logical, Arrow, Ternary, Comparison + scope + keyword.operator.logical, storage.type.function, keyword.operator.bitwise, keyword.operator.ternary, keyword.operator.comparison, keyword.operator.relational, keyword.operator.or.regexp + settings + + foreground + #bb9af7 + + + + name + Tag + scope + entity.name.tag, entity.name.tag support.class.component, meta.tag + settings + + foreground + #f7768e + + + + name + Tag Punctuation + scope + punctuation.definition.tag, punctuation.definition.tag.html, punctuation.definition.tag.begin.html, punctuation.definition.tag.end.html + settings + + foreground + #ba3c97 + + + + name + Blade + scope + keyword.blade, entity.name.function.blade + settings + + foreground + #7aa2f7 + + + + name + PHP - Embedded Tag + scope + punctuation.section.embedded.begin.php, punctuation.section.embedded.end.php + settings + + foreground + #0db9d7 + + + + name + Smarty - Twig tag - Blade + scope + punctuation.definition.variable.smarty, punctuation.section.embedded.begin.smarty, punctuation.section.embedded.end.smarty, meta.tag.template.value.twig, punctuation.section.tag.twig, meta.tag.expression.twig, punctuation.definition.tag.expression.twig, punctuation.definition.tag.output.twig, variable.parameter.smarty + settings + + foreground + #7DCFFF + + + + name + Smarty - Twig variable - function + scope + variable.other.property.twig, support.function.twig, meta.function-call.twig, keyword.control.twig, keyword.control.smarty, keyword.operator.other.twig, keyword.operator.comparison.twig, support.function.functions.twig, support.function.functions.twig, keyword.operator.assignment.twig, support.function.filters.twig, support.function.built-in.smarty, keyword.operator.smarty, text.blade text.html.blade custom.compiler.blade.php punctuation.section.embedded.php entity.name.tag.block.any.html, text.blade text.html.blade custom.compiler.blade.php punctuation.section.embedded.php constant.other.inline-data.html, text.blade text.html.blade custom.compiler.blade.php support.function constant.other.inline-data.html + settings + + foreground + #0db9d7 + + + + name + Globals - PHP Constants etc + scope + constant.other.php, variable.other.global.safer, variable.other.global.safer punctuation.definition.variable, variable.other.global, variable.other.global punctuation.definition.variable, constant.other + settings + + foreground + #e0af68 + + + + name + Variables + scope + variable, support.variable, string constant.other.placeholder + settings + + foreground + #c0caf5 + + + + name + Object Variable + scope + variable.other.object, support.module.node + settings + + foreground + #c0caf5 + + + + name + Object Key + scope + meta.object-literal.key, meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js, string.alias.graphql, string.unquoted.graphql, string.unquoted.alias.graphql, meta.field.declaration.ts variable.object.property + settings + + foreground + #73daca + + + + name + Object Property + scope + variable.other.property, support.variable.property, support.variable.property.dom, meta.function-call variable.other.object.property, variable.language.prototype, meta.property.object, variable.other.member + settings + + foreground + #7dcfff + + + + name + Object Property + scope + variable.other.object.property + settings + + foreground + #c0caf5 + + + + name + Object Literal Member lvl 3 (Vue Prop Validation) + scope + meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.object-literal.key + settings + + foreground + #41a6b5 + + + + name + C-related Block Level Variables + scope + source.cpp meta.block variable.other + settings + + foreground + #f7768e + + + + name + Other Variable + scope + support.other.variable + settings + + foreground + #f7768e + + + + name + Methods + scope + meta.class-method.js entity.name.function.js, entity.name.method.js, variable.function.constructor, keyword.other.special-method, storage.type.cs + settings + + foreground + #7aa2f7 + + + + name + Function Definition + scope + entity.name.function, meta.function-call, meta.function-call entity.name.function, variable.function, meta.definition.method entity.name.function, meta.object-literal entity.name.function + settings + + foreground + #7aa2f7 + + + + name + Function Argument + scope + variable.parameter.function.language.special, variable.parameter, meta.function.parameters punctuation.definition.variable, meta.function.parameter variable + settings + + foreground + #e0af68 + + + + name + Constant, Tag Attribute + scope + keyword.other.type.php, storage.type.php, constant.character, constant.escape, keyword.other.unit + settings + + foreground + #bb9af7 + + + + name + Variable Definition + scope + meta.definition.variable variable.other.constant, meta.definition.variable variable.other.readwrite, variable.other.declaration + settings + + foreground + #bb9af7 + + + + name + Inherited Class + scope + entity.other.inherited-class + settings + + fontStyle + + foreground + #bb9af7 + + + + name + Class, Support, DOM, etc + scope + support.class, support.type, variable.other.readwrite.alias, support.orther.namespace.use.php, meta.use.php, support.other.namespace.php, support.type.sys-types, support.variable.dom, support.constant.math, support.type.object.module, support.constant.json, entity.name.namespace, meta.import.qualifier, entity.name.class + settings + + foreground + #0db9d7 + + + + name + Class Name + scope + entity.name + settings + + foreground + #c0caf5 + + + + name + Support Function + scope + support.function + settings + + foreground + #0db9d7 + + + + name + CSS Class and Support + scope + source.css support.type.property-name, source.sass support.type.property-name, source.scss support.type.property-name, source.less support.type.property-name, source.stylus support.type.property-name, source.postcss support.type.property-name, support.type.property-name.css, support.type.vendored.property-name, support.type.map.key + settings + + foreground + #7aa2f7 + + + + name + CSS Font + scope + support.constant.font-name, meta.definition.variable + settings + + foreground + #9ece6a + + + + name + CSS Class + scope + entity.other.attribute-name.class, meta.at-rule.mixin.scss entity.name.function.scss + settings + + foreground + #9ece6a + + + + name + CSS ID + scope + entity.other.attribute-name.id + settings + + foreground + #fc7b7b + + + + name + CSS Tag + scope + entity.name.tag.css, entity.name.tag.reference, entity.name.tag.scss + settings + + foreground + #0db9d7 + + + + name + CSS Tag Reference + scope + entity.name.tag.reference + settings + + foreground + #e0af68 + + + + name + CSS Property Separator + scope + meta.property-list punctuation.separator.key-value + settings + + foreground + #9abdf5 + + + + name + CSS Punctuation + scope + meta.property-list, punctuation.definition.entity.css + settings + + foreground + #e0af68 + + + + name + SCSS @ + scope + meta.at-rule.mixin keyword.control.at-rule.mixin, meta.at-rule.include entity.name.function.scss, meta.at-rule.include keyword.control.at-rule.include + settings + + foreground + #bb9af7 + + + + name + SCSS Mixins, Extends, Include Keyword + scope + keyword.control.at-rule.include punctuation.definition.keyword, keyword.control.at-rule.mixin punctuation.definition.keyword, meta.at-rule.include keyword.control.at-rule.include, keyword.control.at-rule.extend punctuation.definition.keyword, meta.at-rule.extend keyword.control.at-rule.extend, entity.other.attribute-name.placeholder.css punctuation.definition.entity.css, meta.at-rule.media keyword.control.at-rule.media, meta.at-rule.mixin keyword.control.at-rule.mixin, meta.at-rule.function keyword.control.at-rule.function, keyword.control punctuation.definition.keyword, meta.at-rule.import.scss entity.other.attribute-name.placeholder.scss punctuation.definition.entity.scss, meta.at-rule.import.scss keyword.control.at-rule.import.scss + settings + + foreground + #9d7cd8 + + + + name + SCSS Include Mixin Argument + scope + meta.property-list meta.at-rule.include + settings + + foreground + #c0caf5 + + + + name + CSS value + scope + support.constant.property-value + settings + + foreground + #ff9e64 + + + + name + Sub-methods + scope + entity.name.module.js, variable.import.parameter.js, variable.other.class.js + settings + + foreground + #c0caf5 + + + + name + Language methods + scope + variable.language + settings + + foreground + #f7768e + + + + name + Variable punctuation + scope + variable.other punctuation.definition.variable + settings + + foreground + #c0caf5 + + + + name + Keyword this with Punctuation, ES7 Bind Operator + scope + source.js constant.other.object.key.js string.unquoted.label.js, variable.language.this punctuation.definition.variable, keyword.other.this + settings + + foreground + #f7768e + + + + name + HTML Attributes + scope + entity.other.attribute-name, text.html.basic entity.other.attribute-name.html, text.html.basic entity.other.attribute-name, text.blade entity.other.attribute-name.class, text.html.smarty entity.other.attribute-name.class + settings + + foreground + #bb9af7 + + + + name + Vue Template attributes + scope + meta.directive.vue punctuation.separator.key-value.html, meta.directive.vue entity.other.attribute-name.html + settings + + foreground + #bb9af7 + + + + name + Vue Template attribute separator + scope + meta.directive.vue punctuation.separator.key-value.html + settings + + foreground + #89ddff + + + + name + CSS IDs + scope + source.sass keyword.control + settings + + foreground + #7aa2f7 + + + + name + CSS psuedo selectors + scope + entity.other.attribute-name.pseudo-class, entity.other.attribute-name.pseudo-element, entity.other.attribute-name.placeholder, meta.property-list meta.property-value + settings + + foreground + #bb9af7 + + + + name + Inserted + scope + markup.inserted + settings + + foreground + #449dab + + + + name + Deleted + scope + markup.deleted + settings + + foreground + #914c54 + + + + name + Changed + scope + markup.changed + settings + + foreground + #6183bb + + + + name + Regular Expressions + scope + string.regexp + settings + + foreground + #b4f9f8 + + + + name + Regular Expressions - Punctuation + scope + punctuation.definition.group + settings + + foreground + #f7768e + + + + name + Regular Expressions - Character Class + scope + constant.other.character-class.regexp + settings + + foreground + #bb9af7 + + + + name + Regular Expressions - Character Class Set + scope + constant.other.character-class.set.regexp, punctuation.definition.character-class.regexp + settings + + foreground + #e0af68 + + + + name + Regular Expressions - Quantifier + scope + keyword.operator.quantifier.regexp + settings + + foreground + #89ddff + + + + name + Regular Expressions - Backslash + scope + constant.character.escape.backslash + settings + + foreground + #c0caf5 + + + + name + Escape Characters + scope + constant.character.escape + settings + + foreground + #89ddff + + + + name + Decorators + scope + tag.decorator.js entity.name.tag.js, tag.decorator.js punctuation.definition.tag.js + settings + + foreground + #7aa2f7 + + + + name + CSS Units + scope + keyword.other.unit + settings + + foreground + #f7768e + + + + name + JSON Key - Level 0 + scope + source.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #7aa2f7 + + + + name + JSON Key - Level 1 + scope + source.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #0db9d7 + + + + name + JSON Key - Level 2 + scope + source.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #7dcfff + + + + name + JSON Key - Level 3 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #bb9af7 + + + + name + JSON Key - Level 4 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #e0af68 + + + + name + JSON Key - Level 5 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #0db9d7 + + + + name + JSON Key - Level 6 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #73daca + + + + name + JSON Key - Level 7 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json + settings + + foreground + #f7768e + + + + name + JSON Key - Level 8 + scope + source.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.value.json meta.sequence.json meta.mapping.key.json string.quoted.double.json punctuation.definition.string.end.json + settings + + foreground + #9ece6a + + + + name + JSON Key - value + scope + source.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json, source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.array.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #9ece6a + + + + name + Plain Punctuation + scope + punctuation.definition.list_item.markdown + settings + + foreground + #9abdf5 + + + + name + Block Punctuation + scope + meta.block, meta.brace, punctuation.definition.block, punctuation.definition.use, punctuation.definition.group.shell, punctuation.definition.class, punctuation.definition.begin.bracket, punctuation.definition.end.bracket, punctuation.definition.parameters, punctuation.definition.arguments, punctuation.definition.dictionary, punctuation.definition.array, punctuation.section + settings + + foreground + #9abdf5 + + + + name + Markdown - Plain + scope + meta.jsx.children, meta.embedded.block + settings + + foreground + #c0caf5 + + + + name + HTML text + scope + text.html + settings + + foreground + #9aa5ce + + + + name + Markdown - Markup Raw Inline + scope + text.html.markdown markup.inline.raw.markdown + settings + + foreground + #bb9af7 + + + + name + Markdown - Markup Raw Inline Punctuation + scope + text.html.markdown markup.inline.raw.markdown punctuation.definition.raw.markdown + settings + + foreground + #4E5579 + + + + name + Markdown - Heading 1 + scope + heading.1.markdown entity.name, heading.1.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #89ddff + + + + name + Markdown - Heading 2 + scope + heading.2.markdown entity.name, heading.2.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #61bdf2 + + + + name + Markdown - Heading 3 + scope + heading.3.markdown entity.name, heading.3.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #7aa2f7 + + + + name + Markdown - Heading 4 + scope + heading.4.markdown entity.name, heading.4.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #6d91de + + + + name + Markdown - Heading 5 + scope + heading.5.markdown entity.name, heading.5.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #9aa5ce + + + + name + Markdown - Heading 6 + scope + heading.6.markdown entity.name, heading.6.markdown punctuation.definition.heading.markdown + settings + + fontStyle + bold + foreground + #747ca1 + + + + name + Markup - Italic + scope + markup.italic, markup.italic punctuation + settings + + fontStyle + italic + foreground + #c0caf5 + + + + name + Markup - Bold + scope + markup.bold, markup.bold punctuation + settings + + fontStyle + bold + foreground + #c0caf5 + + + + name + Markup - Bold-Italic + scope + markup.bold markup.italic, markup.bold markup.italic punctuation + settings + + fontStyle + bold italic + foreground + #c0caf5 + + + + name + Markup - Underline + scope + markup.underline, markup.underline punctuation + settings + + fontStyle + underline + + + + name + Markdown - Blockquote + scope + markup.quote punctuation.definition.blockquote.markdown + settings + + foreground + #4e5579 + + + + name + Markup - Quote + scope + markup.quote + settings + + fontStyle + italic + + + + name + Markdown - Link + scope + string.other.link, markup.underline.link, constant.other.reference.link.markdown, string.other.link.description.title.markdown + settings + + foreground + #73daca + + + + name + Markdown - Fenced Code Block + scope + markup.fenced_code.block.markdown, markup.inline.raw.string.markdown, variable.language.fenced.markdown + settings + + foreground + #89ddff + + + + name + Markdown - Separator + scope + meta.separator + settings + + fontStyle + bold + foreground + #444b6a + + + + name + Markup - Table + scope + markup.table + settings + + foreground + #c0cefc + + + + name + Token - Info + scope + token.info-token + settings + + foreground + #0db9d7 + + + + name + Token - Warn + scope + token.warn-token + settings + + foreground + #ffdb69 + + + + name + Token - Error + scope + token.error-token + settings + + foreground + #db4b4b + + + + name + Token - Debug + scope + token.debug-token + settings + + foreground + #b267e6 + + + + name + Apache Tag + scope + entity.tag.apacheconf + settings + + foreground + #f7768e + + + + name + Preprocessor + scope + meta.preprocessor + settings + + foreground + #73daca + + + + name + ENV value + scope + source.env + settings + + foreground + #7aa2f7 + + + + uuid + 06f855e3-9fb7-4fb1-b790-aef06065f34e + + diff --git a/yazi/.config/yazi/init.lua b/yazi/.config/yazi/init.lua index 64398eb..33826fd 100644 --- a/yazi/.config/yazi/init.lua +++ b/yazi/.config/yazi/init.lua @@ -1,93 +1,98 @@ -- Change this to switch themes -local THEME = "rose_pine" +-- local THEME = "kanagawa" +-- local THEME = "catppuccin-mocha" +-- local THEME = "everforest-medium" +local THEME = "gruvbox-material" +-- local THEME = "tokyo-night" +-- local THEME = "rose_pine-moon" -local theme_colors = { - rose_pine = { - primary = "#c4a7e7", -- iris/mauve (purple-like color from rose-pine palette) - secondary = "#6e6a86", -- muted/subtle (comparable to comment/gray colors) - yanked = "#9ccfd8", -- foam (cyan-like accent color) - cut = "#eb6f92", -- love (red-like accent color) - }, - carbonfox = { - primary = "#78a9ff", - secondary = "#525252", - yanked = "#3ddbd9", - cut = "#ff7eb6", - }, - kanagawa = { - primary = "#7e9cd8", - secondary = "#54546d", - yanked = "#7aa89f", - cut = "#e82424", - }, - sonokai = { - primary = "#76cce0", - secondary = "#7f8490", - yanked = "#fc5d7c", - cut = "#f85e84", - }, - catppuccin = { - primary = "#89b4fa", - secondary = "#6c7086", - yanked = "#94e2d5", - cut = "#f38ba8", - }, - dracula = { - primary = "#bd93f9", -- purple - secondary = "#6272a4", -- comment - yanked = "#8be9fd", -- cyan - cut = "#ff5555", -- red - }, - everforest = { - primary = "#7fbbb3", -- aqua - secondary = "#859289", -- gray - yanked = "#a7c080", -- green - cut = "#e67e80", -- red - }, - gruvbox = { - primary = "#7daea3", -- aqua - secondary = "#7c6f64", -- gray - yanked = "#a9b665", -- green - cut = "#ea6962", -- red - }, - nightfox = { - primary = "#719cd6", -- blue - secondary = "#738091", -- comment - yanked = "#63cdcf", -- cyan - cut = "#c94f6d", -- red - }, - onedark = { - primary = "#61afef", -- blue - secondary = "#5c6370", -- gray - yanked = "#56b6c2", -- cyan - cut = "#e06c75", -- red - }, -} +-- local theme_colors = { +-- rose_pine = { +-- primary = "#c4a7e7", -- iris/mauve (purple-like color from rose-pine palette) +-- secondary = "#6e6a86", -- muted/subtle (comparable to comment/gray colors) +-- yanked = "#9ccfd8", -- foam (cyan-like accent color) +-- cut = "#eb6f92", -- love (red-like accent color) +-- }, +-- carbonfox = { +-- primary = "#78a9ff", +-- secondary = "#525252", +-- yanked = "#3ddbd9", +-- cut = "#ff7eb6", +-- }, +-- kanagawa = { +-- primary = "#7e9cd8", +-- secondary = "#54546d", +-- yanked = "#7aa89f", +-- cut = "#e82424", +-- }, +-- sonokai = { +-- primary = "#76cce0", +-- secondary = "#7f8490", +-- yanked = "#fc5d7c", +-- cut = "#f85e84", +-- }, +-- catppuccin = { +-- primary = "#89b4fa", +-- secondary = "#6c7086", +-- yanked = "#94e2d5", +-- cut = "#f38ba8", +-- }, +-- dracula = { +-- primary = "#bd93f9", -- purple +-- secondary = "#6272a4", -- comment +-- yanked = "#8be9fd", -- cyan +-- cut = "#ff5555", -- red +-- }, +-- everforest = { +-- primary = "#7fbbb3", -- aqua +-- secondary = "#859289", -- gray +-- yanked = "#a7c080", -- green +-- cut = "#e67e80", -- red +-- }, +-- gruvbox = { +-- primary = "#7daea3", -- aqua +-- secondary = "#7c6f64", -- gray +-- yanked = "#a9b665", -- green +-- cut = "#ea6962", -- red +-- }, +-- nightfox = { +-- primary = "#719cd6", -- blue +-- secondary = "#738091", -- comment +-- yanked = "#63cdcf", -- cyan +-- cut = "#c94f6d", -- red +-- }, +-- onedark = { +-- primary = "#61afef", -- blue +-- secondary = "#5c6370", -- gray +-- yanked = "#56b6c2", -- cyan +-- cut = "#e06c75", -- red +-- }, +-- } -local c = theme_colors[THEME] +-- eocal c = theme_colors[THEME] -require("yaziline"):setup({ - color = c.primary, - secondary_color = c.secondary, - default_files_color = "darkgray", - selected_files_color = "white", - yanked_files_color = c.yanked, - cut_files_color = c.cut, - separator_style = "angly", -- "angly" | "curvy" | "liney" | "empty" - separator_open = "", - separator_close = "", - separator_open_thin = "", - separator_close_thin = "", - separator_head = "", - separator_tail = "", +-- require("yaziline"):setup({ +-- color = c.primary, +-- secondary_color = c.secondary, +-- default_files_color = "darkgray", +-- selected_files_color = "white", +-- yanked_files_color = c.yanked, +-- cut_files_color = c.cut, +-- separator_style = "angly", -- "angly" | "curvy" | "liney" | "empty" +-- separator_open = "", +-- separator_close = "", +-- separator_open_thin = "", +-- separator_close_thin = "", +-- separator_head = "", +-- separator_tail = "", - select_symbol = "", - yank_symbol = "󰆐", +-- select_symbol = "", +-- yank_symbol = "󰆐", - filename_max_length = 24, -- truncate when filename > 24 - filename_truncate_length = 6, -- leave 6 chars on both sides - filename_truncate_separator = "...", -}) +-- filename_max_length = 24, -- truncate when filename > 24 +-- filename_truncate_length = 6, -- leave 6 chars on both sides +-- filename_truncate_separator = "...", +-- }) require("recycle-bin"):setup({ trash_dir = "~/.local/share/Trash/", diff --git a/yazi/.config/yazi/omp/omp.toml b/yazi/.config/yazi/omp/omp.toml index e11f934..c760e2b 100644 --- a/yazi/.config/yazi/omp/omp.toml +++ b/yazi/.config/yazi/omp/omp.toml @@ -3,12 +3,12 @@ pwd = "osc7" version = 3 [palette] -gb_bright_path = "#9ccdf8" -gb_bright_git = "#f6c177" +gb_bright_path = "#7daea3" +gb_bright_git = "#d8a657" gb_dark0_hard = "#3e7fb0" gb_faded_green = "#79740e" gb_faded_red = "#ea9a97" -gb_text = "#c4a7e7" +gb_text = "#d3869b" [var] user = "" @@ -21,14 +21,14 @@ alignment = "left" [[blocks.segments]] template = '{{ .HostName }} ' -foreground = 'p:gb_text' +foreground = 'magenta' background = 'transparent' type = 'text' style = 'plain' [[blocks.segments]] template = '{{ .UserName }} ' -foreground = 'p:gb_text' +foreground = 'magenta' background = 'transparent' type = 'text' style = 'plain' @@ -38,7 +38,7 @@ style = 'plain' [[blocks.segments]] template = "{{ .Path }} " -foreground = "p:gb_bright_path" +foreground = "blue" background = "transparent" type = "path" style = "plain" @@ -49,7 +49,7 @@ enable_hyperlink = true [[blocks.segments]] template = ' {{ .HEAD }}{{ if or (.Working.Changed) (.Staging.Changed) }}*{{ end }} {{ if gt .Behind 0 }}⇣{{ end }}{{ if gt .Ahead 0 }}⇡{{ end }}' -foreground = "p:gb_bright_git" +foreground = "yellow" background = "transparent" type = "git" style = "plain" diff --git a/yazi/.config/yazi/omp/omp_rose-pine.toml b/yazi/.config/yazi/omp/omp_rose-pine.toml new file mode 100644 index 0000000..e11f934 --- /dev/null +++ b/yazi/.config/yazi/omp/omp_rose-pine.toml @@ -0,0 +1,103 @@ +"$schema" = "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json" +pwd = "osc7" +version = 3 + +[palette] +gb_bright_path = "#9ccdf8" +gb_bright_git = "#f6c177" +gb_dark0_hard = "#3e7fb0" +gb_faded_green = "#79740e" +gb_faded_red = "#ea9a97" +gb_text = "#c4a7e7" + +[var] +user = "" +ssh = "🌐" + +# LEFT SIDE PROMPT +[[blocks]] +type = "prompt" +alignment = "left" + +[[blocks.segments]] +template = '{{ .HostName }} ' +foreground = 'p:gb_text' +background = 'transparent' +type = 'text' +style = 'plain' + +[[blocks.segments]] +template = '{{ .UserName }} ' +foreground = 'p:gb_text' +background = 'transparent' +type = 'text' +style = 'plain' + +# [blocks.segments.properties] +# cache_duration = "none" + +[[blocks.segments]] +template = "{{ .Path }} " +foreground = "p:gb_bright_path" +background = "transparent" +type = "path" +style = "plain" + +[blocks.segments.properties] +style = "full" +enable_hyperlink = true + +[[blocks.segments]] +template = ' {{ .HEAD }}{{ if or (.Working.Changed) (.Staging.Changed) }}*{{ end }} {{ if gt .Behind 0 }}⇣{{ end }}{{ if gt .Ahead 0 }}⇡{{ end }}' +foreground = "p:gb_bright_git" +background = "transparent" +type = "git" +style = "plain" + +[blocks.segments.properties] +fetch_status = true + +[blocks.segments.properties.status_formats] +Added = "+%d" +Deleted = "-%d" +Modified = "~%d" +Untracked = "?%d" + +# RIGHT SIDE PROMPT +[[blocks]] +type = "rprompt" +alignment = "right" + +[[blocks.segments]] +template = " {{ .Full }}" +foreground = "p:gb_faded_green" +background = "transparent" +type = "node" +style = "plain" + +[blocks.segments.properties] +display_mode = "files" + +[[blocks.segments]] +template = " {{ if .Venv }}({{ .Venv }}) {{ end }}{{ .Full }}" +foreground = "p:gb_faded_green" +background = "transparent" +type = "python" +style = "plain" + +[blocks.segments.properties] +display_mode = "always" +fetch_virtual_env = true + +# NEWLINE FOR INPUT +[[blocks]] +type = "prompt" +alignment = "left" +newline = true + +[[blocks.segments]] +template = "❯ " +foreground = "p:gb_bright_aqua" +background = "transparent" +type = "text" +style = "plain" diff --git a/yazi/.config/yazi/package.toml b/yazi/.config/yazi/package.toml index 10d1fe3..9026e65 100644 --- a/yazi/.config/yazi/package.toml +++ b/yazi/.config/yazi/package.toml @@ -142,3 +142,33 @@ hash = "b951d27afe197d154f6da9683b46c5f8" use = "Mintass/rose-pine-moon" rev = "94385fe" hash = "edbe0dfb5db8ff37281dba62adc7e750" + +[[flavor.deps]] +use = "Chromium-3-Oxide/everforest-medium" +rev = "0158f0f" +hash = "a7c36abf0b13289aceb1c20a17c6a63e" + +[[flavor.deps]] +use = "bennyyip/gruvbox-dark" +rev = "619fdc5" +hash = "d4c7003ec6dc4efd5d3a050d5c2f2575" + +[[flavor.deps]] +use = "BennyOe/tokyo-night" +rev = "8e6296f" +hash = "d9da921c3bd37ba32ee27a8a7a40461f" + +[[flavor.deps]] +use = "dangooddd/kanagawa" +rev = "04985d1" +hash = "c69a63981e254a3a06a11c2bf0e6af1d" + +[[flavor.deps]] +use = "matt-dong-123/gruvbox-material" +rev = "6c36491" +hash = "564f2335540ee2c440c3b671bc28ac60" + +[[flavor.deps]] +use = "malick-tammal/monokai" +rev = "e59f6cb" +hash = "dcb449d46e30dc020e4b7b59202d2448" diff --git a/yazi/.config/yazi/plugins/mime-ext.yazi/main.lua b/yazi/.config/yazi/plugins/mime-ext.yazi/main.lua index 2734a40..9a84336 100644 --- a/yazi/.config/yazi/plugins/mime-ext.yazi/main.lua +++ b/yazi/.config/yazi/plugins/mime-ext.yazi/main.lua @@ -1,1130 +1,1129 @@ --- @since 25.12.29 local FILES = { - [".envrc"] = "text/plain", - [".gitconfig"] = "text/plain", - [".gitignore"] = "text/plain", - [".luacheckrc"] = "text/lua", - [".npmrc"] = "text/plain", - [".styluaignore"] = "text/plain", - [".zshenv"] = "text/plain", - [".zshrc"] = "text/plain", - ["cargo.lock"] = "application/json", - ["flake.lock"] = "application/json", - license = "text/plain", - config ="text/plain", + [".envrc"] = "text/plain", + [".gitconfig"] = "text/plain", + [".gitignore"] = "text/plain", + [".luacheckrc"] = "text/lua", + [".npmrc"] = "text/plain", + [".styluaignore"] = "text/plain", + [".zshenv"] = "text/plain", + [".zshrc"] = "text/plain", + ["cargo.lock"] = "application/json", + ["flake.lock"] = "application/json", + license = "text/plain", + config = "text/plain", } local EXTS = { - ["123"] = "application/lotus-1-2-3", - ["3dml"] = "text/in3d.3dml", - ["3ds"] = "image/3ds", - ["3g2"] = "video/3gpp2", - ["3gp"] = "video/3gpp", - ["7z"] = "application/7z-compressed", - ["for"] = "text/fortran", - ["in"] = "text/plain", - ["n-gage"] = "application/nokia.n-gage.symbian.install", - ["sfd-hdstx"] = "application/hydrostatix.sof-data", - aab = "application/authorware-bin", - aac = "audio/aac", - aam = "application/authorware-map", - aas = "application/authorware-seg", - abw = "application/abiword", - ac = "application/pkix-attr-cert", - acc = "application/americandynamics.acc", - ace = "application/ace-compressed", - acu = "application/acucobol", - acutc = "application/acucorp", - adp = "audio/adpcm", - aep = "application/audiograph", - afm = "application/font-type1", - afp = "application/ibm.modcap", - ahead = "application/ahead.space", - ai = "application/postscript", - aif = "audio/aiff", - aifc = "audio/aiff", - aiff = "audio/aiff", - air = "application/adobe.air-application-installer-package+zip", - ait = "application/dvb.ait", - ami = "application/amiga.ami", - apk = "application/android.package-archive", - appcache = "text/cache-manifest", - application = "application/ms-application", - apr = "application/lotus-approach", - arc = "application/freearc", - asc = "application/pgp-signature", - asf = "video/ms-asf", - asm = "text/asm", - aso = "application/accpac.simply.aso", - ass = "text/ass", - asx = "video/ms-asf", - atc = "application/acucorp", - atom = "application/atom+xml", - atomcat = "application/atomcat+xml", - atomsvc = "application/atomsvc+xml", - atx = "application/antix.game-component", - au = "audio/basic", - avi = "video/msvideo", - avif = "image/avif", - aw = "application/applixware", - azf = "application/airzip.filesecure.azf", - azs = "application/airzip.filesecure.azs", - azw = "application/amazon.ebook", - bash = "text/shellscript", - bat = "application/msdownload", - bcpio = "application/bcpio", - bdf = "application/font-bdf", - bdm = "application/syncml.dm+wbxml", - bean = "text/plain", - beancount = "text/plain", - bed = "application/realvnc.bed", - bh2 = "application/fujitsu.oasysprs", - bin = "application/octet-stream", - blb = "application/blorb", - blorb = "application/blorb", - bmi = "application/bmi", - bmp = "image/bmp", - book = "application/framemaker", - box = "application/previewsystems.box", - boz = "application/bzip2", - bpk = "application/octet-stream", - btif = "image/prs.btif", - bz = "application/bzip", - bz2 = "application/bzip2", - c = "text/c", - c11amc = "application/cluetrust.cartomobile-config", - c11amz = "application/cluetrust.cartomobile-config-pkg", - c4d = "application/clonk.c4group", - c4f = "application/clonk.c4group", - c4g = "application/clonk.c4group", - c4p = "application/clonk.c4group", - c4u = "application/clonk.c4group", - cab = "application/ms-cab-compressed", - caf = "audio/caf", - cap = "application/tcpdump.pcap", - car = "application/curl.car", - cat = "application/ms-pki.seccat", - cb7 = "application/cbr", - cba = "application/cbr", - cbr = "application/cbr", - cbt = "application/cbr", - cbz = "application/cbr", - cc = "text/c", - cct = "application/director", - ccxml = "application/ccxml+xml", - cdbcmsg = "application/contact.cmsg", - cdf = "application/netcdf", - cdkey = "application/mediastation.cdkey", - cdmia = "application/cdmi-capability", - cdmic = "application/cdmi-container", - cdmid = "application/cdmi-domain", - cdmio = "application/cdmi-object", - cdmiq = "application/cdmi-queue", - cdx = "chemical/cdx", - cdxml = "application/chemdraw+xml", - cdy = "application/cinderella", - cer = "application/pkix-cert", - cfg = "text/plain", - cfs = "application/cfs-compressed", - cgm = "image/cgm", - chat = "application/chat", - chm = "application/ms-htmlhelp", - chrt = "application/kde.kchart", - cif = "chemical/cif", - cii = "application/anser-web-certificate-issue-initiation", - cil = "application/ms-artgalry", - cla = "application/claymore", - class = "application/java-vm", - clkk = "application/crick.clicker.keyboard", - clkp = "application/crick.clicker.palette", - clkt = "application/crick.clicker.template", - clkw = "application/crick.clicker.wordbank", - clkx = "application/crick.clicker", - clp = "application/msclip", - cmc = "application/cosmocaller", - cmdf = "chemical/cmdf", - cml = "chemical/cml", - cmp = "application/yellowriver-custom-menu", - cmx = "image/cmx", - cod = "application/rim.cod", - com = "application/msdownload", - conf = "text/plain", - config ="text/plain", - cpio = "application/cpio", - cpp = "text/c", - cpt = "application/mac-compactpro", - crd = "application/mscardfile", - crl = "application/pkix-crl", - crt = "application/x509-ca-cert", - cryptonote = "application/rig.cryptonote", - csh = "application/csh", - csml = "chemical/csml", - csp = "application/commonspace", - css = "text/css", - cst = "application/director", - csv = "text/csv", - cu = "application/cu-seeme", - curl = "text/curl", - cww = "application/prs.cww", - cxt = "application/director", - cxx = "text/c", - dae = "model/collada+xml", - daf = "application/mobius.daf", - dart = "application/dart", - dataless = "application/fdsn.seed", - davmount = "application/davmount+xml", - dbk = "application/docbook+xml", - dcr = "application/director", - dcurl = "text/curl.dcurl", - dd2 = "application/oma.dd2+xml", - ddd = "application/fujixerox.ddd", - deb = "application/debian-package", - def = "text/plain", - deploy = "application/octet-stream", - der = "application/x509-ca-cert", - dfac = "application/dreamfactory", - dgc = "application/dgc-compressed", - dic = "text/c", - dir = "application/director", - dis = "application/mobius.dis", - dist = "application/octet-stream", - distz = "application/octet-stream", - djv = "image/djvu", - djvu = "image/djvu", - dll = "application/msdownload", - dmg = "application/apple-diskimage", - dmp = "application/tcpdump.pcap", - dms = "application/octet-stream", - dna = "application/dna", - doc = "application/msword", - docm = "application/ms-word.document.macroenabled.12", - docx = "application/openxmlformats-officedocument.wordprocessingml.document", - dot = "application/msword", - dotm = "application/ms-word.template.macroenabled.12", - dotx = "application/openxmlformats-officedocument.wordprocessingml.template", - dp = "application/osgi.dp", - dpg = "application/dpgraph", - dra = "audio/dra", - dsc = "text/prs.lines.tag", - dssc = "application/dssc+der", - dtb = "application/dtbook+xml", - dtd = "application/xml-dtd", - dts = "audio/dts", - dtshd = "audio/dts.hd", - dump = "application/octet-stream", - dvb = "video/dvb.file", - dvi = "application/dvi", - dwf = "model/dwf", - dwg = "image/dwg", - dxf = "image/dxf", - dxp = "application/spotfire.dxp", - dxr = "application/director", - ebuild = "application/gentoo.ebuild", - ecelp4800 = "audio/nuera.ecelp4800", - ecelp7470 = "audio/nuera.ecelp7470", - ecelp9600 = "audio/nuera.ecelp9600", - eclass = "application/gentoo.eclass", - ecma = "application/ecmascript", - edm = "application/novadigm.edm", - edx = "application/novadigm.edx", - efif = "application/picsel", - ei6 = "application/pg.osasli", - elc = "application/octet-stream", - emf = "application/msmetafile", - eml = "message/rfc822", - emma = "application/emma+xml", - emz = "application/msmetafile", - env = "text/plain", - eol = "audio/digital-winds", - eot = "application/ms-fontobject", - eps = "application/postscript", - epub = "application/epub+zip", - es3 = "application/eszigno3+xml", - esa = "application/osgi.subsystem", - esf = "application/epson.esf", - et3 = "application/eszigno3+xml", - etx = "text/setext", - eva = "application/eva", - evy = "application/envoy", - exe = "application/msdownload", - exi = "application/exi", - ext = "application/novadigm.ext", - ez = "application/andrew-inset", - ez2 = "application/ezpix-album", - ez3 = "application/ezpix-package", - f = "text/fortran", - f4v = "video/f4v", - f77 = "text/fortran", - f90 = "text/fortran", - fbs = "image/fastbidsheet", - fcdt = "application/adobe.formscentral.fcdt", - fcs = "application/isac.fcs", - fdf = "application/fdf", - fe_launch = "application/denovo.fcselayout-link", - fg5 = "application/fujitsu.oasysgp", - fgd = "application/director", - fh = "image/freehand", - fh4 = "image/freehand", - fh5 = "image/freehand", - fh7 = "image/freehand", - fhc = "image/freehand", - fig = "application/xfig", - fish = "text/shellscript", - flac = "audio/flac", - fli = "video/fli", - flo = "application/micrografx.flo", - flv = "video/flv", - flw = "application/kde.kivio", - flx = "text/fmi.flexstor", - fly = "text/fly", - fm = "application/framemaker", - fnc = "application/frogans.fnc", - fpx = "image/fpx", - frame = "application/framemaker", - fsc = "application/fsc.weblaunch", - fst = "image/fst", - ftc = "application/fluxtime.clip", - fti = "application/anser-web-funds-transfer-initiation", - fvt = "video/fvt", - fxp = "application/adobe.fxp", - fxpl = "application/adobe.fxp", - fzs = "application/fuzzysheet", - g2w = "application/geoplan", - g3 = "image/g3fax", - g3w = "application/geospace", - gac = "application/groove-account", - gam = "application/tads", - gbr = "application/rpki-ghostbusters", - gca = "application/gca-compressed", - gdl = "model/gdl", - geo = "application/dynageo", - gex = "application/geometry-explorer", - ggb = "application/geogebra.file", - ggs = "application/geogebra.slides", - ggt = "application/geogebra.tool", - ghf = "application/groove-help", - gif = "image/gif", - gim = "application/groove-identity-message", - gml = "application/gml+xml", - gmx = "application/gmx", - gnumeric = "application/gnumeric", - go = "text/go", - gph = "application/flographit", - gpx = "application/gpx+xml", - gqf = "application/grafeq", - gqs = "application/grafeq", - gram = "application/srgs", - gramps = "application/gramps-xml", - gre = "application/geometry-explorer", - grv = "application/groove-injector", - grxml = "application/srgs+xml", - gsf = "application/font-ghostscript", - gtar = "application/gtar", - gtm = "application/groove-tool-message", - gtw = "model/gtw", - gv = "text/graphviz", - gxf = "application/gxf", - gxt = "application/geonext", - h = "text/c", - h261 = "video/h261", - h263 = "video/h263", - h264 = "video/h264", - hal = "application/hal+xml", - hbci = "application/hbci", - hcl = "text/hcl", - hdf = "application/hdf", - hh = "text/c", - hlp = "application/winhlp", - hpgl = "application/hp-hpgl", - hpid = "application/hp-hpid", - hpp = "text/c", - hps = "application/hp-hps", - hqx = "application/mac-binhex40", - htke = "application/kenameaapp", - htm = "text/html", - html = "text/html", - hvd = "application/yamaha.hv-dic", - hvp = "application/yamaha.hv-voice", - hvs = "application/yamaha.hv-script", - i2g = "application/intergeo", - icc = "application/iccprofile", - ice = "conference/cooltalk", - icm = "application/iccprofile", - ico = "image/icon", - ics = "text/calendar", - ief = "image/ief", - ifb = "text/calendar", - ifm = "application/shana.informed.formdata", - iges = "model/iges", - igl = "application/igloader", - igm = "application/insors.igm", - igs = "model/iges", - igx = "application/micrografx.igx", - iif = "application/shana.informed.interchange", - imp = "application/accpac.simply.imp", - ims = "application/ms-ims", - ini = "text/plain", - ink = "application/inkml+xml", - inkml = "application/inkml+xml", - install = "application/install-instructions", - iota = "application/astraea-software.iota", - ipfix = "application/ipfix", - ipk = "application/shana.informed.package", - irm = "application/ibm.rights-management", - irp = "application/irepository.package+xml", - iso = "application/iso9660-image", - itp = "application/shana.informed.formtemplate", - ivp = "application/immervision-ivp", - ivu = "application/immervision-ivu", - jad = "text/sun.j2me.app-descriptor", - jam = "application/jam", - jar = "application/java-archive", - java = "text/java-source", - jisp = "application/jisp", - jlt = "application/hp-jlyt", - jnlp = "application/java-jnlp-file", - joda = "application/joost.joda-archive", - jpe = "image/jpeg", - jpeg = "image/jpeg", - jpg = "image/jpeg", - jpgm = "video/jpm", - jpgv = "video/jpeg", - jpm = "video/jpm", - js = "text/javascript", - json = "application/json", - jsonc = "application/json", - jsonml = "application/jsonml+json", - jsx = "text/jsx", - jxl = "image/jxl", - kar = "audio/midi", - karbon = "application/kde.karbon", - kdl = "text/kdl", - kfo = "application/kde.kformula", - kia = "application/kidspiration", - kml = "application/google-earth.kml+xml", - kmz = "application/google-earth.kmz", - kne = "application/kinar", - knp = "application/kinar", - kon = "application/kde.kontour", - kpr = "application/kde.kpresenter", - kpt = "application/kde.kpresenter", - kpxx = "application/ds-keypoint", - ksp = "application/kde.kspread", - ktr = "application/kahootz", - ktx = "image/ktx", - ktz = "application/kahootz", - kwd = "application/kde.kword", - kwt = "application/kde.kword", - lasxml = "application/las.las+xml", - latex = "application/latex", - lbd = "application/llamagraphics.life-balance.desktop", - lbe = "application/llamagraphics.life-balance.exchange+xml", - les = "application/hhe.lesson-player", - lha = "application/lzh-compressed", - link66 = "application/route66.link66+xml", - list = "text/plain", - list3820 = "application/ibm.modcap", - listafp = "application/ibm.modcap", - lnk = "application/ms-shortcut", - log = "text/plain", - lostxml = "application/lost+xml", - lrf = "application/octet-stream", - lrm = "application/ms-lrm", - ltf = "application/frogans.ltf", - lua = "text/lua", - lvp = "audio/lucent.voice", - lwp = "application/lotus-wordpro", - lzh = "application/lzh-compressed", - m13 = "application/msmediaview", - m14 = "application/msmediaview", - m1v = "video/mpeg", - m21 = "application/mp21", - m2a = "audio/mpeg", - m2t = "video/mp2t", - m2ts = "video/mp2t", - m2v = "video/mpeg", - m3a = "audio/mpeg", - m3u = "audio/mpegurl", - m3u8 = "application/apple.mpegurl", - m4a = "audio/mp4", - m4u = "video/mpegurl", - m4v = "video/m4v", - ma = "application/mathematica", - mads = "application/mads+xml", - mag = "application/ecowin.chart", - maker = "application/framemaker", - man = "text/troff", - mar = "application/octet-stream", - mathml = "application/mathml+xml", - mb = "application/mathematica", - mbk = "application/mobius.mbk", - mbox = "application/mbox", - mc1 = "application/medcalcdata", - mcd = "application/mcd", - mcurl = "text/curl.mcurl", - md = "text/markdown", - mdb = "application/msaccess", - mdi = "image/ms-modi", - me = "text/troff", - mesh = "model/mesh", - meta4 = "application/metalink4+xml", - metalink = "application/metalink+xml", - mets = "application/mets+xml", - mfm = "application/mfmp", - mft = "application/rpki-manifest", - mgp = "application/osgeo.mapguide.package", - mgz = "application/proteus.magazine", - mid = "audio/midi", - midi = "audio/midi", - mie = "application/mie", - mif = "application/mif", - mime = "message/rfc822", - mj2 = "video/mj2", - mjp2 = "video/mj2", - mjs = "text/javascript", - mk3d = "video/matroska", - mka = "audio/matroska", - mks = "video/matroska", - mkv = "video/matroska", - mlp = "application/dolby.mlp", - mmd = "application/chipnuts.karaoke-mmd", - mmf = "application/smaf", - mmr = "image/fujixerox.edmics-mmr", - mng = "video/mng", - mny = "application/msmoney", - mobi = "application/mobipocket-ebook", - mods = "application/mods+xml", - mov = "video/quicktime", - movie = "video/sgi-movie", - mp2 = "audio/mpeg", - mp21 = "application/mp21", - mp2a = "audio/mpeg", - mp3 = "audio/mpeg", - mp4 = "video/mp4", - mp4a = "audio/mp4", - mp4s = "application/mp4", - mp4v = "video/mp4", - mpc = "application/mophun.certificate", - mpe = "video/mpeg", - mpeg = "video/mpeg", - mpg = "video/mpeg", - mpg4 = "video/mp4", - mpga = "audio/mpeg", - mpkg = "application/apple.installer+xml", - mpm = "application/blueice.multipass", - mpn = "application/mophun.application", - mpp = "application/ms-project", - mpt = "application/ms-project", - mpy = "application/ibm.minipay", - mqy = "application/mobius.mqy", - mrc = "application/marc", - mrcx = "application/marcxml+xml", - ms = "text/troff", - mscml = "application/mediaservercontrol+xml", - mseed = "application/fdsn.mseed", - mseq = "application/mseq", - msf = "application/epson.msf", - msh = "model/mesh", - msi = "application/msdownload", - msl = "application/mobius.msl", - msty = "application/muvee.style", - mts = "video/mp2t", - mus = "application/musician", - musicxml = "application/recordare.musicxml+xml", - mvb = "application/msmediaview", - mwf = "application/mfer", - mxf = "application/mxf", - mxl = "application/recordare.musicxml", - mxml = "application/xv+xml", - mxs = "application/triscape.mxs", - mxu = "video/mpegurl", - n3 = "text/n3", - nb = "application/mathematica", - nbp = "application/wolfram.player", - nc = "application/netcdf", - ncx = "application/dtbncx+xml", - nfo = "text/nfo", - ngdat = "application/nokia.n-gage.data", - nitf = "application/nitf", - nix = "text/nix", - nlu = "application/neurolanguage.nlu", - nml = "application/enliven", - nnd = "application/noblenet-directory", - nns = "application/noblenet-sealer", - nnw = "application/noblenet-web", - npx = "image/net-fpx", - nsc = "application/conference", - nsf = "application/lotus-notes", - ntf = "application/nitf", - nzb = "application/nzb", - oa2 = "application/fujitsu.oasys2", - oa3 = "application/fujitsu.oasys3", - oas = "application/fujitsu.oasys", - obd = "application/msbinder", - obj = "application/tgif", - oda = "application/oda", - odb = "application/oasis.opendocument.database", - odc = "application/oasis.opendocument.chart", - odf = "application/oasis.opendocument.formula", - odft = "application/oasis.opendocument.formula-template", - odg = "application/oasis.opendocument.graphics", - odi = "application/oasis.opendocument.image", - odm = "application/oasis.opendocument.text-master", - odp = "application/oasis.opendocument.presentation", - ods = "application/oasis.opendocument.spreadsheet", - odt = "application/oasis.opendocument.text", - oga = "audio/ogg", - ogg = "audio/ogg", - ogv = "video/ogg", - ogx = "application/ogg", - omdoc = "application/omdoc+xml", - onepkg = "application/onenote", - onetmp = "application/onenote", - onetoc = "application/onenote", - onetoc2 = "application/onenote", - opf = "application/oebps-package+xml", - opml = "text/opml", - oprc = "application/palm", - opus = "audio/ogg", - org = "application/lotus-organizer", - osf = "application/yamaha.openscoreformat", - osfpvg = "application/yamaha.openscoreformat.osfpvg+xml", - otc = "application/oasis.opendocument.chart-template", - otf = "font/otf", - otg = "application/oasis.opendocument.graphics-template", - oth = "application/oasis.opendocument.text-web", - oti = "application/oasis.opendocument.image-template", - otp = "application/oasis.opendocument.presentation-template", - ots = "application/oasis.opendocument.spreadsheet-template", - ott = "application/oasis.opendocument.text-template", - oxps = "application/oxps", - oxt = "application/openofficeorg.extension", - p = "text/pascal", - p10 = "application/pkcs10", - p12 = "application/pkcs12", - p7b = "application/pkcs7-certificates", - p7c = "application/pkcs7-mime", - p7m = "application/pkcs7-mime", - p7r = "application/pkcs7-certreqresp", - p7s = "application/pkcs7-signature", - p8 = "application/pkcs8", - pas = "text/pascal", - patch = "text/diff", - paw = "application/pawaafile", - pbd = "application/powerbuilder6", - pbm = "image/portable-bitmap", - pcap = "application/tcpdump.pcap", - pcf = "application/font-pcf", - pcl = "application/hp-pcl", - pclxl = "application/hp-pclxl", - pct = "image/pict", - pcurl = "application/curl.pcurl", - pcx = "image/pcx", - pdb = "application/palm", - pdf = "application/pdf", - pfa = "application/font-type1", - pfb = "application/font-type1", - pfm = "application/font-type1", - pfr = "application/font-tdpfr", - pfx = "application/pkcs12", - pgm = "image/portable-graymap", - pgn = "application/chess-pgn", - pgp = "application/pgp-encrypted", - php = "text/php", - pic = "image/pict", - pkg = "application/octet-stream", - pki = "application/pkixcmp", - pkipath = "application/pkix-pkipath", - plb = "application/3gpp.pic-bw-large", - plc = "application/mobius.plc", - plf = "application/pocketlearn", - pls = "application/pls+xml", - pml = "application/ctc-posml", - png = "image/png", - pnm = "image/portable-anymap", - portpkg = "application/macports.portpkg", - pot = "application/ms-powerpoint", - potm = "application/ms-powerpoint.template.macroenabled.12", - potx = "application/openxmlformats-officedocument.presentationml.template", - ppam = "application/ms-powerpoint.addin.macroenabled.12", - ppd = "application/cups-ppd", - ppm = "image/portable-pixmap", - pps = "application/ms-powerpoint", - ppsm = "application/ms-powerpoint.slideshow.macroenabled.12", - ppsx = "application/openxmlformats-officedocument.presentationml.slideshow", - ppt = "application/ms-powerpoint", - pptm = "application/ms-powerpoint.presentation.macroenabled.12", - pptx = "application/openxmlformats-officedocument.presentationml.presentation", - pqa = "application/palm", - prc = "application/mobipocket-ebook", - pre = "application/lotus-freelance", - prf = "application/pics-rules", - ps = "application/postscript", - psb = "application/3gpp.pic-bw-small", - psd = "image/adobe.photoshop", - psf = "application/font-linux-psf", - pskcxml = "application/pskc+xml", - ptid = "application/pvi.ptid1", - pub = "application/mspublisher", - pvb = "application/3gpp.pic-bw-var", - pwn = "application/3m.post-it-notes", - py = "text/python", - pya = "audio/ms-playready.media.pya", - pyv = "video/ms-playready.media.pyv", - qam = "application/epson.quickanime", - qbo = "application/intu.qbo", - qfx = "application/intu.qfx", - qml = "text/qml", - qps = "application/publishare-delta-tree", - qt = "video/quicktime", - qwd = "application/quark.quarkxpress", - qwt = "application/quark.quarkxpress", - qxb = "application/quark.quarkxpress", - qxd = "application/quark.quarkxpress", - qxl = "application/quark.quarkxpress", - qxt = "application/quark.quarkxpress", - r = "text/r", - ra = "audio/pn-realaudio", - ram = "audio/pn-realaudio", - rar = "application/rar", - ras = "image/cmu-raster", - rb = "text/ruby", - rcprofile = "application/ipunplugged.rcprofile", - rdf = "application/rdf+xml", - rdz = "application/data-vision.rdz", - rep = "application/businessobjects", - res = "application/dtbresource+xml", - rgb = "image/rgb", - rif = "application/reginfo+xml", - rip = "audio/rip", - ris = "application/research-info-systems", - rl = "application/resource-lists+xml", - rlc = "image/fujixerox.edmics-rlc", - rld = "application/resource-lists-diff+xml", - rm = "application/rn-realmedia", - rmi = "audio/midi", - rmp = "audio/pn-realaudio-plugin", - rms = "application/jcp.javame.midlet-rms", - rmvb = "application/rn-realmedia-vbr", - rnc = "application/relax-ng-compact-syntax", - roa = "application/rpki-roa", - roff = "text/troff", - rp9 = "application/cloanto.rp9", - rpm = "application/rpm", - rpss = "application/nokia.radio-presets", - rpst = "application/nokia.radio-preset", - rq = "application/sparql-query", - rs = "text/rust", - rsd = "application/rsd+xml", - rss = "application/rss+xml", - rtf = "application/rtf", - rtx = "text/richtext", - s = "text/asm", - s3m = "audio/s3m", - saf = "application/yamaha.smaf-audio", - sbml = "application/sbml+xml", - sc = "application/ibm.secure-container", - scd = "application/msschedule", - scm = "application/lotus-screencam", - scq = "application/scvp-cv-request", - scs = "application/scvp-cv-response", - scss = "text/scss", - scurl = "text/curl.scurl", - sda = "application/stardivision.draw", - sdc = "application/stardivision.calc", - sdd = "application/stardivision.impress", - sdkd = "application/solent.sdkm+xml", - sdkm = "application/solent.sdkm+xml", - sdp = "application/sdp", - sdw = "application/stardivision.writer", - see = "application/seemail", - seed = "application/fdsn.seed", - sema = "application/sema", - semd = "application/semd", - semf = "application/semf", - ser = "application/java-serialized-object", - setpay = "application/set-payment-initiation", - setreg = "application/set-registration-initiation", - sfs = "application/spotfire.sfs", - sfv = "text/sfv", - sgi = "image/sgi", - sgl = "application/stardivision.writer-global", - sgm = "text/sgml", - sgml = "text/sgml", - sh = "text/shellscript", - shar = "application/shar", - shf = "application/shf+xml", - sid = "image/mrsid-image", - sig = "application/pgp-signature", - sil = "audio/silk", - silo = "model/mesh", - sis = "application/symbian.install", - sisx = "application/symbian.install", - sit = "application/stuffit", - sitx = "application/stuffitx", - skd = "application/koan", - skm = "application/koan", - skp = "application/koan", - skt = "application/koan", - sldm = "application/ms-powerpoint.slide.macroenabled.12", - sldx = "application/openxmlformats-officedocument.presentationml.slide", - slt = "application/epson.salt", - sm = "application/stepmania.stepchart", - smf = "application/stardivision.math", - smi = "application/smil+xml", - smil = "application/smil+xml", - smv = "video/smv", - smzip = "application/stepmania.package", - snd = "audio/basic", - snf = "application/font-snf", - so = "application/octet-stream", - spc = "application/pkcs7-certificates", - spf = "application/yamaha.smaf-phrase", - spl = "application/futuresplash", - spot = "text/in3d.spot", - spp = "application/scvp-vp-response", - spq = "application/scvp-vp-request", - spx = "audio/ogg", - sql = "application/sql", - src = "application/wais-source", - srt = "application/subrip", - sru = "application/sru+xml", - srx = "application/sparql-results+xml", - ssdl = "application/ssdl+xml", - sse = "application/kodak-descriptor", - ssf = "application/epson.ssf", - ssml = "application/ssml+xml", - st = "application/sailingtracker.track", - stc = "application/sun.xml.calc.template", - std = "application/sun.xml.draw.template", - stf = "application/wt.stf", - sti = "application/sun.xml.impress.template", - stk = "application/hyperstudio", - stl = "application/ms-pki.stl", - str = "application/pg.format", - stw = "application/sun.xml.writer.template", - sub = "text/dvb.subtitle", - sus = "application/sus-calendar", - susp = "application/sus-calendar", - sv4cpio = "application/sv4cpio", - sv4crc = "application/sv4crc", - svc = "application/dvb.service", - svd = "application/svd", - svg = "image/svg+xml", - svgz = "image/svg+xml", - swa = "application/director", - swf = "application/shockwave-flash", - swi = "application/aristanetworks.swi", - sxc = "application/sun.xml.calc", - sxd = "application/sun.xml.draw", - sxg = "application/sun.xml.writer.global", - sxi = "application/sun.xml.impress", - sxm = "application/sun.xml.math", - sxw = "application/sun.xml.writer", - t = "text/troff", - t3 = "application/t3vm-image", - taglet = "application/mynfc", - tao = "application/tao.intent-module-archive", - tar = "application/tar", - tcap = "application/3gpp2.tcap", - tcl = "application/tcl", - teacher = "application/smart.teacher", - tei = "application/tei+xml", - teicorpus = "application/tei+xml", - tex = "application/tex", - texi = "application/texinfo", - texinfo = "application/texinfo", - text = "text/plain", - tf = "text/hcl", - tfi = "application/thraud+xml", - tfm = "application/tex-tfm", - tfrc = "text/hcl", - tfstate = "application/json", - tfvars = "text/hcl", - tga = "image/tga", - thmx = "application/ms-officetheme", - tif = "image/tiff", - tiff = "image/tiff", - tmo = "application/tmobile-livetv", - tmTheme = "text/plain", - toml = "text/toml", - torrent = "application/bittorrent", - tpl = "application/groove-tool-template", - tpt = "application/trid.tpt", - tr = "text/troff", - tra = "application/trueapp", - trm = "application/msterminal", - ts = "text/typescript", - tsd = "application/timestamped-data", - tsv = "text/tab-separated-values", - tsx = "text/tsx", - ttc = "font/collection", - ttf = "font/ttf", - ttl = "text/turtle", - twd = "application/simtech-mindmapper", - twds = "application/simtech-mindmapper", - txd = "application/genomatix.tuxedo", - txf = "application/mobius.txf", - txt = "text/plain", - u32 = "application/authorware-bin", - udeb = "application/debian-package", - ufd = "application/ufdl", - ufdl = "application/ufdl", - ulx = "application/glulx", - umj = "application/umajin", - unityweb = "application/unity", - uoml = "application/uoml+xml", - uri = "text/uri-list", - uris = "text/uri-list", - urls = "text/uri-list", - ustar = "application/ustar", - utz = "application/uiq.theme", - uu = "text/uuencode", - uva = "audio/dece.audio", - uvd = "application/dece.data", - uvf = "application/dece.data", - uvg = "image/dece.graphic", - uvh = "video/dece.hd", - uvi = "image/dece.graphic", - uvm = "video/dece.mobile", - uvp = "video/dece.pd", - uvs = "video/dece.sd", - uvt = "application/dece.ttml+xml", - uvu = "video/uvvu.mp4", - uvv = "video/dece.video", - uvva = "audio/dece.audio", - uvvd = "application/dece.data", - uvvf = "application/dece.data", - uvvg = "image/dece.graphic", - uvvh = "video/dece.hd", - uvvi = "image/dece.graphic", - uvvm = "video/dece.mobile", - uvvp = "video/dece.pd", - uvvs = "video/dece.sd", - uvvt = "application/dece.ttml+xml", - uvvu = "video/uvvu.mp4", - uvvv = "video/dece.video", - uvvx = "application/dece.unspecified", - uvvz = "application/dece.zip", - uvx = "application/dece.unspecified", - uvz = "application/dece.zip", - vcard = "text/vcard", - vcd = "application/cdlink", - vcf = "text/vcard", - vcg = "application/groove-vcard", - vcs = "text/vcalendar", - vcx = "application/vcx", - vis = "application/visionary", - viv = "video/vivo", - vob = "video/ms-vob", - vor = "application/stardivision.writer", - vox = "application/authorware-bin", - vrml = "model/vrml", - vsd = "application/visio", - vsf = "application/vsf", - vss = "application/visio", - vst = "application/visio", - vsw = "application/visio", - vtu = "model/vtu", - vxml = "application/voicexml+xml", - w3d = "application/director", - wad = "application/doom", - wasm = "application/wasm", - wav = "audio/wav", - wax = "audio/ms-wax", - wbmp = "image/wap.wbmp", - wbs = "application/criticaltools.wbs+xml", - wbxml = "application/wap.wbxml", - wcm = "application/ms-works", - wdb = "application/ms-works", - wdp = "image/ms-photo", - weba = "audio/webm", - webm = "video/webm", - webp = "image/webp", - wg = "application/pmi.widget", - wgt = "application/widget", - wks = "application/ms-works", - wm = "video/ms-wm", - wma = "audio/ms-wma", - wmd = "application/ms-wmd", - wmf = "application/msmetafile", - wml = "text/wap.wml", - wmlc = "application/wap.wmlc", - wmls = "text/wap.wmlscript", - wmlsc = "application/wap.wmlscriptc", - wmv = "video/ms-wmv", - wmx = "video/ms-wmx", - wmz = "application/ms-wmz", - woff = "font/woff", - woff2 = "font/woff2", - wpd = "application/wordperfect", - wpl = "application/ms-wpl", - wps = "application/ms-works", - wqd = "application/wqd", - wri = "application/mswrite", - wrl = "model/vrml", - wsdl = "application/wsdl+xml", - wspolicy = "application/wspolicy+xml", - wtb = "application/webturbo", - wvx = "video/ms-wvx", - x32 = "application/authorware-bin", - x3d = "model/x3d+xml", - x3db = "model/x3d+binary", - x3dbz = "model/x3d+binary", - x3dv = "model/x3d+vrml", - x3dvz = "model/x3d+vrml", - x3dz = "model/x3d+xml", - xaml = "application/xaml+xml", - xap = "application/silverlight-app", - xar = "application/xara", - xbap = "application/ms-xbap", - xbd = "application/fujixerox.docuworks.binder", - xbm = "image/xbitmap", - xdf = "application/xcap-diff+xml", - xdm = "application/syncml.dm+xml", - xdp = "application/adobe.xdp+xml", - xdssc = "application/dssc+xml", - xdw = "application/fujixerox.docuworks", - xenc = "application/xenc+xml", - xer = "application/patch-ops-error+xml", - xfdf = "application/adobe.xfdf", - xfdl = "application/xfdl", - xht = "application/xhtml+xml", - xhtml = "application/xhtml+xml", - xhvml = "application/xv+xml", - xif = "image/xiff", - xla = "application/ms-excel", - xlam = "application/ms-excel.addin.macroenabled.12", - xlc = "application/ms-excel", - xlf = "application/xliff+xml", - xlm = "application/ms-excel", - xls = "application/ms-excel", - xlsb = "application/ms-excel.sheet.binary.macroenabled.12", - xlsm = "application/ms-excel.sheet.macroenabled.12", - xlsx = "application/openxmlformats-officedocument.spreadsheetml.sheet", - xlt = "application/ms-excel", - xltm = "application/ms-excel.template.macroenabled.12", - xltx = "application/openxmlformats-officedocument.spreadsheetml.template", - xlw = "application/ms-excel", - xm = "audio/xm", - xml = "application/xml", - xo = "application/olpc-sugar", - xop = "application/xop+xml", - xpak = "application/gentoo.xpak", - xpi = "application/xpinstall", - xpl = "application/xproc+xml", - xpm = "image/xpixmap", - xpr = "application/is-xpr", - xps = "application/ms-xpsdocument", - xpw = "application/intercon.formnet", - xpx = "application/intercon.formnet", - xsl = "application/xml", - xslt = "application/xslt+xml", - xsm = "application/syncml+xml", - xspf = "application/xspf+xml", - xul = "application/mozilla.xul+xml", - xvm = "application/xv+xml", - xvml = "application/xv+xml", - xwd = "image/xwindowdump", - xyz = "chemical/xyz", - xz = "application/xz", - yaml = "text/yaml", - yang = "application/yang", - yin = "application/yin+xml", - yml = "text/yaml", - z1 = "application/zmachine", - z2 = "application/zmachine", - z3 = "application/zmachine", - z4 = "application/zmachine", - z5 = "application/zmachine", - z6 = "application/zmachine", - z7 = "application/zmachine", - z8 = "application/zmachine", - zaz = "application/zzazz.deck+xml", - zip = "application/zip", - zir = "application/zul", - zirz = "application/zul", - zmm = "application/handheld-entertainment+xml", - zsh = "text/shellscript", + ["123"] = "application/lotus-1-2-3", + ["3dml"] = "text/in3d.3dml", + ["3ds"] = "image/3ds", + ["3g2"] = "video/3gpp2", + ["3gp"] = "video/3gpp", + ["7z"] = "application/7z-compressed", + ["for"] = "text/fortran", + ["in"] = "text/plain", + ["n-gage"] = "application/nokia.n-gage.symbian.install", + ["sfd-hdstx"] = "application/hydrostatix.sof-data", + aab = "application/authorware-bin", + aac = "audio/aac", + aam = "application/authorware-map", + aas = "application/authorware-seg", + abw = "application/abiword", + ac = "application/pkix-attr-cert", + acc = "application/americandynamics.acc", + ace = "application/ace-compressed", + acu = "application/acucobol", + acutc = "application/acucorp", + adp = "audio/adpcm", + aep = "application/audiograph", + afm = "application/font-type1", + afp = "application/ibm.modcap", + ahead = "application/ahead.space", + ai = "application/postscript", + aif = "audio/aiff", + aifc = "audio/aiff", + aiff = "audio/aiff", + air = "application/adobe.air-application-installer-package+zip", + ait = "application/dvb.ait", + ami = "application/amiga.ami", + apk = "application/android.package-archive", + appcache = "text/cache-manifest", + application = "application/ms-application", + apr = "application/lotus-approach", + arc = "application/freearc", + asc = "application/pgp-signature", + asf = "video/ms-asf", + asm = "text/asm", + aso = "application/accpac.simply.aso", + ass = "text/ass", + asx = "video/ms-asf", + atc = "application/acucorp", + atom = "application/atom+xml", + atomcat = "application/atomcat+xml", + atomsvc = "application/atomsvc+xml", + atx = "application/antix.game-component", + au = "audio/basic", + avi = "video/msvideo", + avif = "image/avif", + aw = "application/applixware", + azf = "application/airzip.filesecure.azf", + azs = "application/airzip.filesecure.azs", + azw = "application/amazon.ebook", + bash = "text/shellscript", + bat = "application/msdownload", + bcpio = "application/bcpio", + bdf = "application/font-bdf", + bdm = "application/syncml.dm+wbxml", + bean = "text/plain", + beancount = "text/plain", + bed = "application/realvnc.bed", + bh2 = "application/fujitsu.oasysprs", + bin = "application/octet-stream", + blb = "application/blorb", + blorb = "application/blorb", + bmi = "application/bmi", + bmp = "image/bmp", + book = "application/framemaker", + box = "application/previewsystems.box", + boz = "application/bzip2", + bpk = "application/octet-stream", + btif = "image/prs.btif", + bz = "application/bzip", + bz2 = "application/bzip2", + c = "text/c", + c11amc = "application/cluetrust.cartomobile-config", + c11amz = "application/cluetrust.cartomobile-config-pkg", + c4d = "application/clonk.c4group", + c4f = "application/clonk.c4group", + c4g = "application/clonk.c4group", + c4p = "application/clonk.c4group", + c4u = "application/clonk.c4group", + cab = "application/ms-cab-compressed", + caf = "audio/caf", + cap = "application/tcpdump.pcap", + car = "application/curl.car", + cat = "application/ms-pki.seccat", + cb7 = "application/cbr", + cba = "application/cbr", + cbr = "application/cbr", + cbt = "application/cbr", + cbz = "application/cbr", + cc = "text/c", + cct = "application/director", + ccxml = "application/ccxml+xml", + cdbcmsg = "application/contact.cmsg", + cdf = "application/netcdf", + cdkey = "application/mediastation.cdkey", + cdmia = "application/cdmi-capability", + cdmic = "application/cdmi-container", + cdmid = "application/cdmi-domain", + cdmio = "application/cdmi-object", + cdmiq = "application/cdmi-queue", + cdx = "chemical/cdx", + cdxml = "application/chemdraw+xml", + cdy = "application/cinderella", + cer = "application/pkix-cert", + cfg = "text/plain", + cfs = "application/cfs-compressed", + cgm = "image/cgm", + chat = "application/chat", + chm = "application/ms-htmlhelp", + chrt = "application/kde.kchart", + cif = "chemical/cif", + cii = "application/anser-web-certificate-issue-initiation", + cil = "application/ms-artgalry", + cla = "application/claymore", + class = "application/java-vm", + clkk = "application/crick.clicker.keyboard", + clkp = "application/crick.clicker.palette", + clkt = "application/crick.clicker.template", + clkw = "application/crick.clicker.wordbank", + clkx = "application/crick.clicker", + clp = "application/msclip", + cmc = "application/cosmocaller", + cmdf = "chemical/cmdf", + cml = "chemical/cml", + cmp = "application/yellowriver-custom-menu", + cmx = "image/cmx", + cod = "application/rim.cod", + com = "application/msdownload", + conf = "text/plain", + config = "text/plain", + cpio = "application/cpio", + cpp = "text/c", + cpt = "application/mac-compactpro", + crd = "application/mscardfile", + crl = "application/pkix-crl", + crt = "application/x509-ca-cert", + cryptonote = "application/rig.cryptonote", + csh = "application/csh", + csml = "chemical/csml", + csp = "application/commonspace", + css = "text/css", + cst = "application/director", + csv = "text/csv", + cu = "application/cu-seeme", + curl = "text/curl", + cww = "application/prs.cww", + cxt = "application/director", + cxx = "text/c", + dae = "model/collada+xml", + daf = "application/mobius.daf", + dart = "application/dart", + dataless = "application/fdsn.seed", + davmount = "application/davmount+xml", + dbk = "application/docbook+xml", + dcr = "application/director", + dcurl = "text/curl.dcurl", + dd2 = "application/oma.dd2+xml", + ddd = "application/fujixerox.ddd", + deb = "application/debian-package", + def = "text/plain", + deploy = "application/octet-stream", + der = "application/x509-ca-cert", + dfac = "application/dreamfactory", + dgc = "application/dgc-compressed", + dic = "text/c", + dir = "application/director", + dis = "application/mobius.dis", + dist = "application/octet-stream", + distz = "application/octet-stream", + djv = "image/djvu", + djvu = "image/djvu", + dll = "application/msdownload", + dmg = "application/apple-diskimage", + dmp = "application/tcpdump.pcap", + dms = "application/octet-stream", + dna = "application/dna", + doc = "application/msword", + docm = "application/ms-word.document.macroenabled.12", + docx = "application/openxmlformats-officedocument.wordprocessingml.document", + dot = "application/msword", + dotm = "application/ms-word.template.macroenabled.12", + dotx = "application/openxmlformats-officedocument.wordprocessingml.template", + dp = "application/osgi.dp", + dpg = "application/dpgraph", + dra = "audio/dra", + dsc = "text/prs.lines.tag", + dssc = "application/dssc+der", + dtb = "application/dtbook+xml", + dtd = "application/xml-dtd", + dts = "audio/dts", + dtshd = "audio/dts.hd", + dump = "application/octet-stream", + dvb = "video/dvb.file", + dvi = "application/dvi", + dwf = "model/dwf", + dwg = "image/dwg", + dxf = "image/dxf", + dxp = "application/spotfire.dxp", + dxr = "application/director", + ebuild = "application/gentoo.ebuild", + ecelp4800 = "audio/nuera.ecelp4800", + ecelp7470 = "audio/nuera.ecelp7470", + ecelp9600 = "audio/nuera.ecelp9600", + eclass = "application/gentoo.eclass", + ecma = "application/ecmascript", + edm = "application/novadigm.edm", + edx = "application/novadigm.edx", + efif = "application/picsel", + ei6 = "application/pg.osasli", + elc = "application/octet-stream", + emf = "application/msmetafile", + eml = "message/rfc822", + emma = "application/emma+xml", + emz = "application/msmetafile", + env = "text/plain", + eol = "audio/digital-winds", + eot = "application/ms-fontobject", + eps = "application/postscript", + epub = "application/epub+zip", + es3 = "application/eszigno3+xml", + esa = "application/osgi.subsystem", + esf = "application/epson.esf", + et3 = "application/eszigno3+xml", + etx = "text/setext", + eva = "application/eva", + evy = "application/envoy", + exe = "application/msdownload", + exi = "application/exi", + ext = "application/novadigm.ext", + ez = "application/andrew-inset", + ez2 = "application/ezpix-album", + ez3 = "application/ezpix-package", + f = "text/fortran", + f4v = "video/f4v", + f77 = "text/fortran", + f90 = "text/fortran", + fbs = "image/fastbidsheet", + fcdt = "application/adobe.formscentral.fcdt", + fcs = "application/isac.fcs", + fdf = "application/fdf", + fe_launch = "application/denovo.fcselayout-link", + fg5 = "application/fujitsu.oasysgp", + fgd = "application/director", + fh = "image/freehand", + fh4 = "image/freehand", + fh5 = "image/freehand", + fh7 = "image/freehand", + fhc = "image/freehand", + fig = "application/xfig", + fish = "text/shellscript", + flac = "audio/flac", + fli = "video/fli", + flo = "application/micrografx.flo", + flv = "video/flv", + flw = "application/kde.kivio", + flx = "text/fmi.flexstor", + fly = "text/fly", + fm = "application/framemaker", + fnc = "application/frogans.fnc", + fpx = "image/fpx", + frame = "application/framemaker", + fsc = "application/fsc.weblaunch", + fst = "image/fst", + ftc = "application/fluxtime.clip", + fti = "application/anser-web-funds-transfer-initiation", + fvt = "video/fvt", + fxp = "application/adobe.fxp", + fxpl = "application/adobe.fxp", + fzs = "application/fuzzysheet", + g2w = "application/geoplan", + g3 = "image/g3fax", + g3w = "application/geospace", + gac = "application/groove-account", + gam = "application/tads", + gbr = "application/rpki-ghostbusters", + gca = "application/gca-compressed", + gdl = "model/gdl", + geo = "application/dynageo", + gex = "application/geometry-explorer", + ggb = "application/geogebra.file", + ggs = "application/geogebra.slides", + ggt = "application/geogebra.tool", + ghf = "application/groove-help", + gif = "image/gif", + gim = "application/groove-identity-message", + gml = "application/gml+xml", + gmx = "application/gmx", + gnumeric = "application/gnumeric", + go = "text/go", + gph = "application/flographit", + gpx = "application/gpx+xml", + gqf = "application/grafeq", + gqs = "application/grafeq", + gram = "application/srgs", + gramps = "application/gramps-xml", + gre = "application/geometry-explorer", + grv = "application/groove-injector", + grxml = "application/srgs+xml", + gsf = "application/font-ghostscript", + gtar = "application/gtar", + gtm = "application/groove-tool-message", + gtw = "model/gtw", + gv = "text/graphviz", + gxf = "application/gxf", + gxt = "application/geonext", + h = "text/c", + h261 = "video/h261", + h263 = "video/h263", + h264 = "video/h264", + hal = "application/hal+xml", + hbci = "application/hbci", + hcl = "text/hcl", + hdf = "application/hdf", + hh = "text/c", + hlp = "application/winhlp", + hpgl = "application/hp-hpgl", + hpid = "application/hp-hpid", + hpp = "text/c", + hps = "application/hp-hps", + hqx = "application/mac-binhex40", + htke = "application/kenameaapp", + htm = "text/html", + html = "text/html", + hvd = "application/yamaha.hv-dic", + hvp = "application/yamaha.hv-voice", + hvs = "application/yamaha.hv-script", + i2g = "application/intergeo", + icc = "application/iccprofile", + ice = "conference/cooltalk", + icm = "application/iccprofile", + ico = "image/icon", + ics = "text/calendar", + ief = "image/ief", + ifb = "text/calendar", + ifm = "application/shana.informed.formdata", + iges = "model/iges", + igl = "application/igloader", + igm = "application/insors.igm", + igs = "model/iges", + igx = "application/micrografx.igx", + iif = "application/shana.informed.interchange", + imp = "application/accpac.simply.imp", + ims = "application/ms-ims", + ini = "text/plain", + ink = "application/inkml+xml", + inkml = "application/inkml+xml", + install = "application/install-instructions", + iota = "application/astraea-software.iota", + ipfix = "application/ipfix", + ipk = "application/shana.informed.package", + irm = "application/ibm.rights-management", + irp = "application/irepository.package+xml", + iso = "application/iso9660-image", + itp = "application/shana.informed.formtemplate", + ivp = "application/immervision-ivp", + ivu = "application/immervision-ivu", + jad = "text/sun.j2me.app-descriptor", + jam = "application/jam", + jar = "application/java-archive", + java = "text/java-source", + jisp = "application/jisp", + jlt = "application/hp-jlyt", + jnlp = "application/java-jnlp-file", + joda = "application/joost.joda-archive", + jpe = "image/jpeg", + jpeg = "image/jpeg", + jpg = "image/jpeg", + jpgm = "video/jpm", + jpgv = "video/jpeg", + jpm = "video/jpm", + js = "text/javascript", + json = "application/json", + jsonc = "application/json", + jsonml = "application/jsonml+json", + jsx = "text/jsx", + jxl = "image/jxl", + kar = "audio/midi", + karbon = "application/kde.karbon", + kdl = "text/kdl", + kfo = "application/kde.kformula", + kia = "application/kidspiration", + kml = "application/google-earth.kml+xml", + kmz = "application/google-earth.kmz", + kne = "application/kinar", + knp = "application/kinar", + kon = "application/kde.kontour", + kpr = "application/kde.kpresenter", + kpt = "application/kde.kpresenter", + kpxx = "application/ds-keypoint", + ksp = "application/kde.kspread", + ktr = "application/kahootz", + ktx = "image/ktx", + ktz = "application/kahootz", + kwd = "application/kde.kword", + kwt = "application/kde.kword", + lasxml = "application/las.las+xml", + latex = "application/latex", + lbd = "application/llamagraphics.life-balance.desktop", + lbe = "application/llamagraphics.life-balance.exchange+xml", + les = "application/hhe.lesson-player", + lha = "application/lzh-compressed", + link66 = "application/route66.link66+xml", + list = "text/plain", + list3820 = "application/ibm.modcap", + listafp = "application/ibm.modcap", + lnk = "application/ms-shortcut", + log = "text/plain", + lostxml = "application/lost+xml", + lrf = "application/octet-stream", + lrm = "application/ms-lrm", + ltf = "application/frogans.ltf", + lua = "text/lua", + lvp = "audio/lucent.voice", + lwp = "application/lotus-wordpro", + lzh = "application/lzh-compressed", + m13 = "application/msmediaview", + m14 = "application/msmediaview", + m1v = "video/mpeg", + m21 = "application/mp21", + m2a = "audio/mpeg", + m2t = "video/mp2t", + m2ts = "video/mp2t", + m2v = "video/mpeg", + m3a = "audio/mpeg", + m3u = "audio/mpegurl", + m3u8 = "application/apple.mpegurl", + m4a = "audio/mp4", + m4u = "video/mpegurl", + m4v = "video/m4v", + ma = "application/mathematica", + mads = "application/mads+xml", + mag = "application/ecowin.chart", + maker = "application/framemaker", + man = "text/troff", + mar = "application/octet-stream", + mathml = "application/mathml+xml", + mb = "application/mathematica", + mbk = "application/mobius.mbk", + mbox = "application/mbox", + mc1 = "application/medcalcdata", + mcd = "application/mcd", + mcurl = "text/curl.mcurl", + md = "text/markdown", + mdb = "application/msaccess", + mdi = "image/ms-modi", + me = "text/troff", + mesh = "model/mesh", + meta4 = "application/metalink4+xml", + metalink = "application/metalink+xml", + mets = "application/mets+xml", + mfm = "application/mfmp", + mft = "application/rpki-manifest", + mgp = "application/osgeo.mapguide.package", + mgz = "application/proteus.magazine", + mid = "audio/midi", + midi = "audio/midi", + mie = "application/mie", + mif = "application/mif", + mime = "message/rfc822", + mj2 = "video/mj2", + mjp2 = "video/mj2", + mjs = "text/javascript", + mk3d = "video/matroska", + mka = "audio/matroska", + mks = "video/matroska", + mkv = "video/matroska", + mlp = "application/dolby.mlp", + mmd = "application/chipnuts.karaoke-mmd", + mmf = "application/smaf", + mmr = "image/fujixerox.edmics-mmr", + mng = "video/mng", + mny = "application/msmoney", + mobi = "application/mobipocket-ebook", + mods = "application/mods+xml", + mov = "video/quicktime", + movie = "video/sgi-movie", + mp2 = "audio/mpeg", + mp21 = "application/mp21", + mp2a = "audio/mpeg", + mp3 = "audio/mpeg", + mp4 = "video/mp4", + mp4a = "audio/mp4", + mp4s = "application/mp4", + mp4v = "video/mp4", + mpc = "application/mophun.certificate", + mpe = "video/mpeg", + mpeg = "video/mpeg", + mpg = "video/mpeg", + mpg4 = "video/mp4", + mpga = "audio/mpeg", + mpkg = "application/apple.installer+xml", + mpm = "application/blueice.multipass", + mpn = "application/mophun.application", + mpp = "application/ms-project", + mpt = "application/ms-project", + mpy = "application/ibm.minipay", + mqy = "application/mobius.mqy", + mrc = "application/marc", + mrcx = "application/marcxml+xml", + ms = "text/troff", + mscml = "application/mediaservercontrol+xml", + mseed = "application/fdsn.mseed", + mseq = "application/mseq", + msf = "application/epson.msf", + msh = "model/mesh", + msi = "application/msdownload", + msl = "application/mobius.msl", + msty = "application/muvee.style", + mts = "video/mp2t", + mus = "application/musician", + musicxml = "application/recordare.musicxml+xml", + mvb = "application/msmediaview", + mwf = "application/mfer", + mxf = "application/mxf", + mxl = "application/recordare.musicxml", + mxml = "application/xv+xml", + mxs = "application/triscape.mxs", + mxu = "video/mpegurl", + n3 = "text/n3", + nb = "application/mathematica", + nbp = "application/wolfram.player", + nc = "application/netcdf", + ncx = "application/dtbncx+xml", + nfo = "text/nfo", + ngdat = "application/nokia.n-gage.data", + nitf = "application/nitf", + nix = "text/nix", + nlu = "application/neurolanguage.nlu", + nml = "application/enliven", + nnd = "application/noblenet-directory", + nns = "application/noblenet-sealer", + nnw = "application/noblenet-web", + npx = "image/net-fpx", + nsc = "application/conference", + nsf = "application/lotus-notes", + ntf = "application/nitf", + nzb = "application/nzb", + oa2 = "application/fujitsu.oasys2", + oa3 = "application/fujitsu.oasys3", + oas = "application/fujitsu.oasys", + obd = "application/msbinder", + obj = "application/tgif", + oda = "application/oda", + odb = "application/oasis.opendocument.database", + odc = "application/oasis.opendocument.chart", + odf = "application/oasis.opendocument.formula", + odft = "application/oasis.opendocument.formula-template", + odg = "application/oasis.opendocument.graphics", + odi = "application/oasis.opendocument.image", + odm = "application/oasis.opendocument.text-master", + odp = "application/oasis.opendocument.presentation", + ods = "application/oasis.opendocument.spreadsheet", + odt = "application/oasis.opendocument.text", + oga = "audio/ogg", + ogg = "audio/ogg", + ogv = "video/ogg", + ogx = "application/ogg", + omdoc = "application/omdoc+xml", + onepkg = "application/onenote", + onetmp = "application/onenote", + onetoc = "application/onenote", + onetoc2 = "application/onenote", + opf = "application/oebps-package+xml", + opml = "text/opml", + oprc = "application/palm", + opus = "audio/ogg", + org = "application/lotus-organizer", + osf = "application/yamaha.openscoreformat", + osfpvg = "application/yamaha.openscoreformat.osfpvg+xml", + otc = "application/oasis.opendocument.chart-template", + otf = "font/otf", + otg = "application/oasis.opendocument.graphics-template", + oth = "application/oasis.opendocument.text-web", + oti = "application/oasis.opendocument.image-template", + otp = "application/oasis.opendocument.presentation-template", + ots = "application/oasis.opendocument.spreadsheet-template", + ott = "application/oasis.opendocument.text-template", + oxps = "application/oxps", + oxt = "application/openofficeorg.extension", + p = "text/pascal", + p10 = "application/pkcs10", + p12 = "application/pkcs12", + p7b = "application/pkcs7-certificates", + p7c = "application/pkcs7-mime", + p7m = "application/pkcs7-mime", + p7r = "application/pkcs7-certreqresp", + p7s = "application/pkcs7-signature", + p8 = "application/pkcs8", + pas = "text/pascal", + patch = "text/diff", + paw = "application/pawaafile", + pbd = "application/powerbuilder6", + pbm = "image/portable-bitmap", + pcap = "application/tcpdump.pcap", + pcf = "application/font-pcf", + pcl = "application/hp-pcl", + pclxl = "application/hp-pclxl", + pct = "image/pict", + pcurl = "application/curl.pcurl", + pcx = "image/pcx", + pdb = "application/palm", + pdf = "application/pdf", + pfa = "application/font-type1", + pfb = "application/font-type1", + pfm = "application/font-type1", + pfr = "application/font-tdpfr", + pfx = "application/pkcs12", + pgm = "image/portable-graymap", + pgn = "application/chess-pgn", + pgp = "application/pgp-encrypted", + php = "text/php", + pic = "image/pict", + pkg = "application/octet-stream", + pki = "application/pkixcmp", + pkipath = "application/pkix-pkipath", + plb = "application/3gpp.pic-bw-large", + plc = "application/mobius.plc", + plf = "application/pocketlearn", + pls = "application/pls+xml", + pml = "application/ctc-posml", + png = "image/png", + pnm = "image/portable-anymap", + portpkg = "application/macports.portpkg", + pot = "application/ms-powerpoint", + potm = "application/ms-powerpoint.template.macroenabled.12", + potx = "application/openxmlformats-officedocument.presentationml.template", + ppam = "application/ms-powerpoint.addin.macroenabled.12", + ppd = "application/cups-ppd", + ppm = "image/portable-pixmap", + pps = "application/ms-powerpoint", + ppsm = "application/ms-powerpoint.slideshow.macroenabled.12", + ppsx = "application/openxmlformats-officedocument.presentationml.slideshow", + ppt = "application/ms-powerpoint", + pptm = "application/ms-powerpoint.presentation.macroenabled.12", + pptx = "application/openxmlformats-officedocument.presentationml.presentation", + pqa = "application/palm", + prc = "application/mobipocket-ebook", + pre = "application/lotus-freelance", + prf = "application/pics-rules", + ps = "application/postscript", + psb = "application/3gpp.pic-bw-small", + psd = "image/adobe.photoshop", + psf = "application/font-linux-psf", + pskcxml = "application/pskc+xml", + ptid = "application/pvi.ptid1", + pub = "application/mspublisher", + pvb = "application/3gpp.pic-bw-var", + pwn = "application/3m.post-it-notes", + py = "text/python", + pya = "audio/ms-playready.media.pya", + pyv = "video/ms-playready.media.pyv", + qam = "application/epson.quickanime", + qbo = "application/intu.qbo", + qfx = "application/intu.qfx", + qml = "text/qml", + qps = "application/publishare-delta-tree", + qt = "video/quicktime", + qwd = "application/quark.quarkxpress", + qwt = "application/quark.quarkxpress", + qxb = "application/quark.quarkxpress", + qxd = "application/quark.quarkxpress", + qxl = "application/quark.quarkxpress", + qxt = "application/quark.quarkxpress", + r = "text/r", + ra = "audio/pn-realaudio", + ram = "audio/pn-realaudio", + rar = "application/rar", + ras = "image/cmu-raster", + rb = "text/ruby", + rcprofile = "application/ipunplugged.rcprofile", + rdf = "application/rdf+xml", + rdz = "application/data-vision.rdz", + rep = "application/businessobjects", + res = "application/dtbresource+xml", + rgb = "image/rgb", + rif = "application/reginfo+xml", + rip = "audio/rip", + ris = "application/research-info-systems", + rl = "application/resource-lists+xml", + rlc = "image/fujixerox.edmics-rlc", + rld = "application/resource-lists-diff+xml", + rm = "application/rn-realmedia", + rmi = "audio/midi", + rmp = "audio/pn-realaudio-plugin", + rms = "application/jcp.javame.midlet-rms", + rmvb = "application/rn-realmedia-vbr", + rnc = "application/relax-ng-compact-syntax", + roa = "application/rpki-roa", + roff = "text/troff", + rp9 = "application/cloanto.rp9", + rpm = "application/rpm", + rpss = "application/nokia.radio-presets", + rpst = "application/nokia.radio-preset", + rq = "application/sparql-query", + rs = "text/rust", + rsd = "application/rsd+xml", + rss = "application/rss+xml", + rtf = "application/rtf", + rtx = "text/richtext", + s = "text/asm", + s3m = "audio/s3m", + saf = "application/yamaha.smaf-audio", + sbml = "application/sbml+xml", + sc = "application/ibm.secure-container", + scd = "application/msschedule", + scm = "application/lotus-screencam", + scq = "application/scvp-cv-request", + scs = "application/scvp-cv-response", + scss = "text/scss", + scurl = "text/curl.scurl", + sda = "application/stardivision.draw", + sdc = "application/stardivision.calc", + sdd = "application/stardivision.impress", + sdkd = "application/solent.sdkm+xml", + sdkm = "application/solent.sdkm+xml", + sdp = "application/sdp", + sdw = "application/stardivision.writer", + see = "application/seemail", + seed = "application/fdsn.seed", + sema = "application/sema", + semd = "application/semd", + semf = "application/semf", + ser = "application/java-serialized-object", + setpay = "application/set-payment-initiation", + setreg = "application/set-registration-initiation", + sfs = "application/spotfire.sfs", + sfv = "text/sfv", + sgi = "image/sgi", + sgl = "application/stardivision.writer-global", + sgm = "text/sgml", + sgml = "text/sgml", + sh = "text/shellscript", + shar = "application/shar", + shf = "application/shf+xml", + sid = "image/mrsid-image", + sig = "application/pgp-signature", + sil = "audio/silk", + silo = "model/mesh", + sis = "application/symbian.install", + sisx = "application/symbian.install", + sit = "application/stuffit", + sitx = "application/stuffitx", + skd = "application/koan", + skm = "application/koan", + skp = "application/koan", + skt = "application/koan", + sldm = "application/ms-powerpoint.slide.macroenabled.12", + sldx = "application/openxmlformats-officedocument.presentationml.slide", + slt = "application/epson.salt", + sm = "application/stepmania.stepchart", + smf = "application/stardivision.math", + smi = "application/smil+xml", + smil = "application/smil+xml", + smv = "video/smv", + smzip = "application/stepmania.package", + snd = "audio/basic", + snf = "application/font-snf", + so = "application/octet-stream", + spc = "application/pkcs7-certificates", + spf = "application/yamaha.smaf-phrase", + spl = "application/futuresplash", + spot = "text/in3d.spot", + spp = "application/scvp-vp-response", + spq = "application/scvp-vp-request", + spx = "audio/ogg", + sql = "application/sql", + src = "application/wais-source", + srt = "application/subrip", + sru = "application/sru+xml", + srx = "application/sparql-results+xml", + ssdl = "application/ssdl+xml", + sse = "application/kodak-descriptor", + ssf = "application/epson.ssf", + ssml = "application/ssml+xml", + st = "application/sailingtracker.track", + stc = "application/sun.xml.calc.template", + std = "application/sun.xml.draw.template", + stf = "application/wt.stf", + sti = "application/sun.xml.impress.template", + stk = "application/hyperstudio", + stl = "application/ms-pki.stl", + str = "application/pg.format", + stw = "application/sun.xml.writer.template", + sub = "text/dvb.subtitle", + sus = "application/sus-calendar", + susp = "application/sus-calendar", + sv4cpio = "application/sv4cpio", + sv4crc = "application/sv4crc", + svc = "application/dvb.service", + svd = "application/svd", + svg = "image/svg+xml", + svgz = "image/svg+xml", + swa = "application/director", + swf = "application/shockwave-flash", + swi = "application/aristanetworks.swi", + sxc = "application/sun.xml.calc", + sxd = "application/sun.xml.draw", + sxg = "application/sun.xml.writer.global", + sxi = "application/sun.xml.impress", + sxm = "application/sun.xml.math", + sxw = "application/sun.xml.writer", + t = "text/troff", + t3 = "application/t3vm-image", + taglet = "application/mynfc", + tao = "application/tao.intent-module-archive", + tar = "application/tar", + tcap = "application/3gpp2.tcap", + tcl = "application/tcl", + teacher = "application/smart.teacher", + tei = "application/tei+xml", + teicorpus = "application/tei+xml", + tex = "application/tex", + texi = "application/texinfo", + texinfo = "application/texinfo", + text = "text/plain", + tf = "text/hcl", + tfi = "application/thraud+xml", + tfm = "application/tex-tfm", + tfrc = "text/hcl", + tfstate = "application/json", + tfvars = "text/hcl", + tga = "image/tga", + theme = "application/plain", + thmx = "application/ms-officetheme", + tif = "image/tiff", + tiff = "image/tiff", + tmo = "application/tmobile-livetv", + tmTheme = "text/plain", + toml = "text/toml", + torrent = "application/bittorrent", + tpl = "application/groove-tool-template", + tpt = "application/trid.tpt", + tr = "text/troff", + tra = "application/trueapp", + trm = "application/msterminal", + ts = "text/typescript", + tsd = "application/timestamped-data", + tsv = "text/tab-separated-values", + tsx = "text/tsx", + ttc = "font/collection", + ttf = "font/ttf", + ttl = "text/turtle", + twd = "application/simtech-mindmapper", + twds = "application/simtech-mindmapper", + txd = "application/genomatix.tuxedo", + txf = "application/mobius.txf", + txt = "text/plain", + u32 = "application/authorware-bin", + udeb = "application/debian-package", + ufd = "application/ufdl", + ufdl = "application/ufdl", + ulx = "application/glulx", + umj = "application/umajin", + unityweb = "application/unity", + uoml = "application/uoml+xml", + uri = "text/uri-list", + uris = "text/uri-list", + urls = "text/uri-list", + ustar = "application/ustar", + utz = "application/uiq.theme", + uu = "text/uuencode", + uva = "audio/dece.audio", + uvd = "application/dece.data", + uvf = "application/dece.data", + uvg = "image/dece.graphic", + uvh = "video/dece.hd", + uvi = "image/dece.graphic", + uvm = "video/dece.mobile", + uvp = "video/dece.pd", + uvs = "video/dece.sd", + uvt = "application/dece.ttml+xml", + uvu = "video/uvvu.mp4", + uvv = "video/dece.video", + uvva = "audio/dece.audio", + uvvd = "application/dece.data", + uvvf = "application/dece.data", + uvvg = "image/dece.graphic", + uvvh = "video/dece.hd", + uvvi = "image/dece.graphic", + uvvm = "video/dece.mobile", + uvvp = "video/dece.pd", + uvvs = "video/dece.sd", + uvvt = "application/dece.ttml+xml", + uvvu = "video/uvvu.mp4", + uvvv = "video/dece.video", + uvvx = "application/dece.unspecified", + uvvz = "application/dece.zip", + uvx = "application/dece.unspecified", + uvz = "application/dece.zip", + vcard = "text/vcard", + vcd = "application/cdlink", + vcf = "text/vcard", + vcg = "application/groove-vcard", + vcs = "text/vcalendar", + vcx = "application/vcx", + vis = "application/visionary", + viv = "video/vivo", + vob = "video/ms-vob", + vor = "application/stardivision.writer", + vox = "application/authorware-bin", + vrml = "model/vrml", + vsd = "application/visio", + vsf = "application/vsf", + vss = "application/visio", + vst = "application/visio", + vsw = "application/visio", + vtu = "model/vtu", + vxml = "application/voicexml+xml", + w3d = "application/director", + wad = "application/doom", + wasm = "application/wasm", + wav = "audio/wav", + wax = "audio/ms-wax", + wbmp = "image/wap.wbmp", + wbs = "application/criticaltools.wbs+xml", + wbxml = "application/wap.wbxml", + wcm = "application/ms-works", + wdb = "application/ms-works", + wdp = "image/ms-photo", + weba = "audio/webm", + webm = "video/webm", + webp = "image/webp", + wg = "application/pmi.widget", + wgt = "application/widget", + wks = "application/ms-works", + wm = "video/ms-wm", + wma = "audio/ms-wma", + wmd = "application/ms-wmd", + wmf = "application/msmetafile", + wml = "text/wap.wml", + wmlc = "application/wap.wmlc", + wmls = "text/wap.wmlscript", + wmlsc = "application/wap.wmlscriptc", + wmv = "video/ms-wmv", + wmx = "video/ms-wmx", + wmz = "application/ms-wmz", + woff = "font/woff", + woff2 = "font/woff2", + wpd = "application/wordperfect", + wpl = "application/ms-wpl", + wps = "application/ms-works", + wqd = "application/wqd", + wri = "application/mswrite", + wrl = "model/vrml", + wsdl = "application/wsdl+xml", + wspolicy = "application/wspolicy+xml", + wtb = "application/webturbo", + wvx = "video/ms-wvx", + x32 = "application/authorware-bin", + x3d = "model/x3d+xml", + x3db = "model/x3d+binary", + x3dbz = "model/x3d+binary", + x3dv = "model/x3d+vrml", + x3dvz = "model/x3d+vrml", + x3dz = "model/x3d+xml", + xaml = "application/xaml+xml", + xap = "application/silverlight-app", + xar = "application/xara", + xbap = "application/ms-xbap", + xbd = "application/fujixerox.docuworks.binder", + xbm = "image/xbitmap", + xdf = "application/xcap-diff+xml", + xdm = "application/syncml.dm+xml", + xdp = "application/adobe.xdp+xml", + xdssc = "application/dssc+xml", + xdw = "application/fujixerox.docuworks", + xenc = "application/xenc+xml", + xer = "application/patch-ops-error+xml", + xfdf = "application/adobe.xfdf", + xfdl = "application/xfdl", + xht = "application/xhtml+xml", + xhtml = "application/xhtml+xml", + xhvml = "application/xv+xml", + xif = "image/xiff", + xla = "application/ms-excel", + xlam = "application/ms-excel.addin.macroenabled.12", + xlc = "application/ms-excel", + xlf = "application/xliff+xml", + xlm = "application/ms-excel", + xls = "application/ms-excel", + xlsb = "application/ms-excel.sheet.binary.macroenabled.12", + xlsm = "application/ms-excel.sheet.macroenabled.12", + xlsx = "application/openxmlformats-officedocument.spreadsheetml.sheet", + xlt = "application/ms-excel", + xltm = "application/ms-excel.template.macroenabled.12", + xltx = "application/openxmlformats-officedocument.spreadsheetml.template", + xlw = "application/ms-excel", + xm = "audio/xm", + xml = "application/xml", + xo = "application/olpc-sugar", + xop = "application/xop+xml", + xpak = "application/gentoo.xpak", + xpi = "application/xpinstall", + xpl = "application/xproc+xml", + xpm = "image/xpixmap", + xpr = "application/is-xpr", + xps = "application/ms-xpsdocument", + xpw = "application/intercon.formnet", + xpx = "application/intercon.formnet", + xsl = "application/xml", + xslt = "application/xslt+xml", + xsm = "application/syncml+xml", + xspf = "application/xspf+xml", + xul = "application/mozilla.xul+xml", + xvm = "application/xv+xml", + xvml = "application/xv+xml", + xwd = "image/xwindowdump", + xyz = "chemical/xyz", + xz = "application/xz", + yaml = "text/yaml", + yang = "application/yang", + yin = "application/yin+xml", + yml = "text/yaml", + z1 = "application/zmachine", + z2 = "application/zmachine", + z3 = "application/zmachine", + z4 = "application/zmachine", + z5 = "application/zmachine", + z6 = "application/zmachine", + z7 = "application/zmachine", + z8 = "application/zmachine", + zaz = "application/zzazz.deck+xml", + zip = "application/zip", + zir = "application/zul", + zirz = "application/zul", + zmm = "application/handheld-entertainment+xml", + zsh = "text/shellscript", } -local options = ya.sync( - function(st) - return { - with_files = st.with_files, - with_exts = st.with_exts, - fallback_file1 = st.fallback_file1, - } - end -) +local options = ya.sync(function(st) + return { + with_files = st.with_files, + with_exts = st.with_exts, + fallback_file1 = st.fallback_file1, + } +end) local M = {} function M:setup(opts) - opts = opts or {} + opts = opts or {} - self.with_files = opts.with_files - self.with_exts = opts.with_exts - self.fallback_file1 = opts.fallback_file1 + self.with_files = opts.with_files + self.with_exts = opts.with_exts + self.fallback_file1 = opts.fallback_file1 end function M:fetch(job) - local opts = options() - local merged_files = ya.dict_merge(FILES, opts.with_files or {}) - local merged_exts = ya.dict_merge(EXTS, opts.with_exts or {}) + local opts = options() + local merged_files = ya.dict_merge(FILES, opts.with_files or {}) + local merged_exts = ya.dict_merge(EXTS, opts.with_exts or {}) - local updates, unknown, state = {}, {}, {} - for i, file in ipairs(job.files) do - if file.cha.is_dummy then - state[i] = false - goto continue - end + local updates, unknown, state = {}, {}, {} + for i, file in ipairs(job.files) do + if file.cha.is_dummy then + state[i] = false + goto continue + end - local mime - if file.cha.len == 0 then - mime = "inode/empty" - else - mime = merged_files[(file.url.name or ""):lower()] - mime = mime or merged_exts[(file.url.ext or ""):lower()] - end + local mime + if file.cha.len == 0 then + mime = "inode/empty" + else + mime = merged_files[(file.url.name or ""):lower()] + mime = mime or merged_exts[(file.url.ext or ""):lower()] + end - if mime then - updates[tostring(file.url)], state[i] = mime, true - elseif opts.fallback_file1 then - unknown[#unknown + 1] = file - else - updates[tostring(file.url)], state[i] = "application/octet-stream", true - end - ::continue:: - end + if mime then + updates[tostring(file.url)], state[i] = mime, true + elseif opts.fallback_file1 then + unknown[#unknown + 1] = file + else + updates[tostring(file.url)], state[i] = "application/octet-stream", true + end + ::continue:: + end - if next(updates) then - ya.emit("update_mimes", { updates = updates }) - end + if next(updates) then + ya.emit("update_mimes", { updates = updates }) + end - if #unknown > 0 then - return self.fallback_builtin(job, unknown, state) - end + if #unknown > 0 then + return self.fallback_builtin(job, unknown, state) + end - return state + return state end function M.fallback_builtin(job, unknown, state) - local indices = {} - for i, f in ipairs(job.files) do - indices[f:hash()] = i - end + local indices = {} + for i, f in ipairs(job.files) do + indices[f:hash()] = i + end - local result = require("mime.local"):fetch(ya.dict_merge(job, { files = unknown })) - for i, f in ipairs(unknown) do - if type(result) == "table" then - state[indices[f:hash()]] = result[i] - else - state[indices[f:hash()]] = result - end - end - return state + local result = require("mime.local"):fetch(ya.dict_merge(job, { files = unknown })) + for i, f in ipairs(unknown) do + if type(result) == "table" then + state[indices[f:hash()]] = result[i] + else + state[indices[f:hash()]] = result + end + end + return state end return M diff --git a/yazi/.config/yazi/plugins/whoosh.yazi/bookmarks b/yazi/.config/yazi/plugins/whoosh.yazi/bookmarks index 62be25f..85cd038 100644 --- a/yazi/.config/yazi/plugins/whoosh.yazi/bookmarks +++ b/yazi/.config/yazi/plugins/whoosh.yazi/bookmarks @@ -4,6 +4,7 @@ tex /home/liph/Documents/tex D,t tank /mnt/tank t,t scripts /home/liph/scripts d,s r /home/liph/Documents/r D,r +programming /home/liph/programming p podman /mnt/flash1/podman t,p ohmyposh /home/liph/dotfiles/ohmyposh/.config/ohmyposh d,o obsidian /home/liph/Documents/obsidian/vault D,o diff --git a/yazi/.config/yazi/theme.toml b/yazi/.config/yazi/theme.toml deleted file mode 120000 index a82b5b5..0000000 --- a/yazi/.config/yazi/theme.toml +++ /dev/null @@ -1 +0,0 @@ -/home/liph/.config/yazi/themes/rose.toml \ No newline at end of file diff --git a/yazi/.config/yazi/themes/cat.toml b/yazi/.config/yazi/themes/cat.toml deleted file mode 100644 index 15de14f..0000000 --- a/yazi/.config/yazi/themes/cat.toml +++ /dev/null @@ -1,187 +0,0 @@ -# vim:fileencoding=utf-8:foldmethod=marker - -# : Manager {{{ - -[mgr] -cwd = { fg = "#94e2d5" } - -# TODO: remove -# Hovered -hovered = { reversed = true } -preview_hovered = { underline = true } - -# Find -find_keyword = { fg = "#f9e2af", bold = true, italic = true, underline = true } -find_position = { fg = "#f5c2e7", bg = "reset", bold = true, italic = true } - -# Marker -marker_copied = { fg = "#a6e3a1", bg = "#a6e3a1" } -marker_cut = { fg = "#f38ba8", bg = "#f38ba8" } -marker_marked = { fg = "#94e2d5", bg = "#94e2d5" } -marker_selected = { fg = "#f9e2af", bg = "#f9e2af" } - -# Count -count_copied = { fg = "#1e1e2e", bg = "#a6e3a1" } -count_cut = { fg = "#1e1e2e", bg = "#f38ba8" } -count_selected = { fg = "#1e1e2e", bg = "#f9e2af" } - -# Border -border_symbol = "│" -border_style = { fg = "#7f849c" } - -# : }}} - - -# : Tabs {{{ - -[tabs] -active = { fg = "#1e1e2e", bg = "#89b4fa", bold = true } -inactive = { fg = "#89b4fa", bg = "#313244" } - -# : }}} - - -# : Mode {{{ - -[mode] - -normal_main = { fg = "#1e1e2e", bg = "#89b4fa", bold = true } -normal_alt = { fg = "#89b4fa", bg = "#313244" } - -# Select mode -select_main = { fg = "#1e1e2e", bg = "#94e2d5", bold = true } -select_alt = { fg = "#94e2d5", bg = "#313244" } - -# Unset mode -unset_main = { fg = "#1e1e2e", bg = "#f2cdcd", bold = true } -unset_alt = { fg = "#f2cdcd", bg = "#313244" } - -# : }}} - - -# : Status bar {{{ - -[status] -# Permissions -perm_sep = { fg = "#7f849c" } -perm_type = { fg = "#89b4fa" } -perm_read = { fg = "#f9e2af" } -perm_write = { fg = "#f38ba8" } -perm_exec = { fg = "#a6e3a1" } - -# Progress -progress_label = { fg = "#ffffff", bold = true } -progress_normal = { fg = "#a6e3a1", bg = "#45475a" } -progress_error = { fg = "#f9e2af", bg = "#f38ba8" } - -# : }}} - - -# : Pick {{{ - -[pick] -border = { fg = "#89b4fa" } -active = { fg = "#f5c2e7", bold = true } -inactive = {} - -# : }}} - - -# : Input {{{ - -[input] -border = { fg = "#89b4fa" } -title = {} -value = {} -selected = { reversed = true } - -# : }}} - - -# : Completion {{{ - -[cmp] -border = { fg = "#89b4fa" } - -# : }}} - - -# : Tasks {{{ - -[tasks] -border = { fg = "#89b4fa" } -title = {} -hovered = { fg = "#f5c2e7", bold = true } - -# : }}} - - -# : Which {{{ - -[which] -mask = { bg = "#313244" } -cand = { fg = "#94e2d5" } -rest = { fg = "#9399b2" } -desc = { fg = "#f5c2e7" } -separator = "  " -separator_style = { fg = "#585b70" } - -# : }}} - - -# : Help {{{ - -[help] -on = { fg = "#94e2d5" } -run = { fg = "#f5c2e7" } -hovered = { reversed = true, bold = true } -footer = { fg = "#313244", bg = "#cdd6f4" } - -# : }}} - - -# : Spotter {{{ - -[spot] -border = { fg = "#89b4fa" } -title = { fg = "#89b4fa" } -tbl_col = { fg = "#94e2d5" } -tbl_cell = { fg = "#f5c2e7", bg = "#45475a" } - -# : }}} - - -# : Notification {{{ - -[notify] -title_info = { fg = "#a6e3a1" } -title_warn = { fg = "#f9e2af" } -title_error = { fg = "#f38ba8" } - -# : }}} - - -# : File-specific styles {{{ - -[filetype] - -rules = [ - # Image - { mime = "image/*", fg = "#94e2d5" }, - # Media - { mime = "{audio,video}/*", fg = "#f9e2af" }, - # Archive - { mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#f5c2e7" }, - # Document - { mime = "application/{pdf,doc,rtf}", fg = "#a6e3a1" }, - # Virtual file system - { mime = "vfs/{absent,stale}", fg = "#9399b2" }, - # Fallback - { url = "*", fg = "#cdd6f4" }, - { url = "*/", fg = "#89b4fa" }, - # TODO: remove - { name = "*", fg = "#cdd6f4" }, - { name = "*/", fg = "#89b4fa" } -] - -# : }}} diff --git a/yazi/.config/yazi/themes/dracula.toml b/yazi/.config/yazi/themes/dracula.toml deleted file mode 100644 index 58b0080..0000000 --- a/yazi/.config/yazi/themes/dracula.toml +++ /dev/null @@ -1,318 +0,0 @@ -# Theme Configuration -[theme] -# Theme metadata -name = "Dracula Pro" -author = "Enhanced Dracula Theme" -version = "2.0.0" -description = "A sophisticated dark theme based on Dracula color scheme" - -# Color palette definition -[theme.colors] -background = "#282a36" -current_line = "#44475a" -foreground = "#f8f8f2" -comment = "#6272a4" -purple = "#bd93f9" -green = "#50fa7b" -orange = "#ffb86c" -red = "#ff5555" -pink = "#ff79c6" -cyan = "#8be9fd" -yellow = "#f1fa8c" - -# Animation settings -[theme.animation] -frames_per_second = 60 -duration = 0.2 -easing = "easeInOutCubic" - -# Manager -[manager] -# Enhanced preview options -preview = { tab_size = 2, max_width = 100, max_height = 50, cache_size = 50, scroll_offset = 5 } -preview_ratios = [1, 4, 4] -preview_shown = true -preview_service = { image = "ueberzug", video = "ffmpegthumbnailer", pdf = "pdftoppm" } - -# Sophisticated hover effects -hovered = { fg = "#f8f8f2", bg = "#44475a", italic = true } - -# Enhanced markers with animations -marker_copied = { fg = "#282a36", bg = "#50fa7b" } - -# Dynamic loading indicators -loading_indicator_frames = "⣾⣽⣻⢿⡿⣟⣯⣷" -loading_style = { fg = "#bd93f9", bold = true } - -# Enhanced folder icons -folder_icons = { default = " ", open = " ", empty = " ", empty_open = " ", symlink = " ", symlink_open = " ", error = " " } - -file_size_units = ["B", "KB", "MB", "GB", "TB", "PB", "EB"] - -# Status -[status] -# Dynamic status bar -refresh_rate = 1000 -separator_open = "" -separator_close = "" - -# Progress bar styling -progress_bar_style = { fg = "#bd93f9", bg = "#44475a" } - -# Enhanced modes -mode_normal = { fg = "#282a36", bg = "#bd93f9", bold = true } - -# Input -[input] -# Advanced input styling -cursor_style = { fg = "#f8f8f2", bg = "#6272a4", blink = true, blink_interval = 500 } - -# History features -history_size = 100 -history_unique = true - -# Completion styling -completion_style = { selected_bg = "#44475a", selected_fg = "#f8f8f2", selected_bold = true, selected_italic = true } - -# Notify -[notify] -# Enhanced notification system -position = "top-right" -timeout = 5000 -max_width = 400 -max_height = 200 -margin = 10 -padding = 8 - -[notify.levels] -info = { fg = "#50fa7b", bg = "#282a36", icon = " ", timeout = 3000 } -warn = { fg = "#f1fa8c", bg = "#282a36", icon = " ", timeout = 5000 } -error = { fg = "#ff5555", bg = "#282a36", icon = " ", timeout = 7000 } -debug = { fg = "#6272a4", bg = "#282a36", icon = "󰃤 ", timeout = 2000 } - -[notify.animation] -enabled = true -duration = 200 -slide_in = "right" -fade_out = true - -[notify.border] -fg = "#bd93f9" -bg = "#282a36" -style = "rounded" - -[notify.overlay] -bg = "#282a36" -blend = 0.8 - -# File-specific styles -[filetype] -rules = [ - # Development Environment - { name = ".env*", fg = "#50fa7b", bold = true, prefix = "󰙪 " }, - { name = ".git*", fg = "#ff5555", italic = true, prefix = " " }, - { name = ".docker*", fg = "#8be9fd", bold = true, prefix = "󰡨 " }, - - # Configuration Files - { name = "*.{json,yaml,yml,toml,xml}", fg = "#8be9fd", italic = true, prefix = "󰘦 " }, - { name = "*.{ini,conf,cfg}", fg = "#6272a4", italic = true, prefix = " " }, - - # Web Development - { name = "*.{html,htm}", fg = "#ff79c6", italic = true, prefix = "󰌝 " }, - { name = "*.{css,scss,sass,less}", fg = "#bd93f9", italic = true, prefix = "󰌜 " }, - { name = "*.{jsx,tsx}", fg = "#8be9fd", italic = true, prefix = "󰜈 " }, - { name = "*.{js,ts}", fg = "#f1fa8c", italic = true, prefix = "󰌞 " }, - { name = "*.vue", fg = "#50fa7b", italic = true, prefix = "󰡄 " }, - { name = "*.svelte", fg = "#ff5555", italic = true, prefix = "󰓓 " }, - - # Backend Development - { name = "*.{py,pyc}", fg = "#50fa7b", italic = true, prefix = "󰌠 " }, - { name = "*.{rb,erb}", fg = "#ff5555", italic = true, prefix = "󰴭 " }, - { name = "*.{php,phar}", fg = "#bd93f9", italic = true, prefix = "󰌟 " }, - { name = "*.{java,jar}", fg = "#ff5555", italic = true, prefix = "󰬷 " }, - { name = "*.go", fg = "#8be9fd", italic = true, prefix = "󰟓 " }, - { name = "*.rs", fg = "#ff7043", italic = true, prefix = "󱘗 " }, - - # System Programming - { name = "*.{c,h}", fg = "#bd93f9", italic = true, prefix = "󰙱 " }, - { name = "*.{cpp,hpp}", fg = "#ff79c6", italic = true, prefix = "󰙲 " }, - { name = "*.{asm,s}", fg = "#ff5555", italic = true, prefix = "󰋖 " }, - - # Build Systems - { name = "*Makefile", fg = "#ff79c6", bold = true, prefix = "󰛕 " }, - { name = "*CMakeLists.txt", fg = "#ff79c6", bold = true, prefix = "󰔷 " }, - { name = "*.gradle", fg = "#8be9fd", bold = true, prefix = "󰏗 " }, - - # Package Managers - { name = "package.json", fg = "#ff5555", bold = true, prefix = "󰎙 " }, - { name = "package-lock.json", fg = "#ff5555", italic = true, prefix = "󰎙 " }, - { name = "composer.json", fg = "#ff79c6", bold = true, prefix = "󰎙 " }, - { name = "Cargo.toml", fg = "#ff7043", bold = true, prefix = "󱘗 " }, - - # Documentation - { name = "*.{md,mdx}", fg = "#f1fa8c", italic = true, prefix = "󰍔 " }, - { name = "*.rst", fg = "#f1fa8c", italic = true, prefix = "󰈙 " }, - { name = "*.pdf", fg = "#ff5555", bold = true, prefix = "󰈙 " }, - { name = "LICENSE*", fg = "#50fa7b", bold = true, prefix = "󰿃 " }, - { name = "README*", fg = "#50fa7b", bold = true, prefix = " " }, - - # Media with size categories - { name = "*.{jpg,jpeg,png,gif}", size = "< 1MB", fg = "#8be9fd", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "< 10MB", fg = "#ffb86c", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "> 10MB", fg = "#ff5555", prefix = "󰋯 " }, - - # Video files with duration indicator - { name = "*.{mp4,mkv}", duration = "< 10:00", fg = "#bd93f9", prefix = "󰕧 " }, - { name = "*.{mp4,mkv}", duration = "< 1:00:00", fg = "#ffb86c", prefix = "󰕧 " }, - { name = "*.{mp4,mkv}", duration = "> 1:00:00", fg = "#ff5555", prefix = "󰕧 " }, - - # Archives with compression ratio - { name = "*.{zip,gz,tar}", ratio = "< 0.5", fg = "#50fa7b", prefix = "󰀼 " }, - { name = "*.{zip,gz,tar}", ratio = "< 0.7", fg = "#f1fa8c", prefix = "󰀼 " }, - { name = "*.{zip,gz,tar}", ratio = "> 0.7", fg = "#ff5555", prefix = "󰀼 " }, - - # Special Directories - { name = "node_modules", fg = "#6272a4", prefix = "󰎙 " }, - { name = ".git", fg = "#ff5555", prefix = " " }, - { name = ".github", fg = "#bd93f9", prefix = " " }, - { name = "dist", fg = "#6272a4", prefix = "󰏗 " }, - { name = "build", fg = "#6272a4", prefix = "󱁤 " }, - - # Additional file types - # Audio files - { name = "*.{mp3,flac,m4a,wav,ogg}", fg = "#bd93f9", italic = true, prefix = "󰎈 " }, - - # Font files - { name = "*.{ttf,otf,woff,woff2}", fg = "#ff79c6", italic = true, prefix = "󰛖 " }, - - # Database files - { name = "*.{sql,sqlite,db}", fg = "#8be9fd", italic = true, prefix = "󰆼 " }, - - # Shell scripts - { name = "*.{sh,bash,zsh,fish}", fg = "#50fa7b", italic = true, prefix = "󰆍 " }, - - # Virtual environments - { name = "venv", fg = "#6272a4", prefix = "󰆧 " }, - { name = ".env", fg = "#50fa7b", prefix = "󰆧 " }, - - # Container files - { name = "*.dockerfile", fg = "#8be9fd", bold = true, prefix = "󰡨 " }, - { name = "docker-compose*.{yml,yaml}", fg = "#8be9fd", bold = true, prefix = "󰡨 " }, - - # Security files - { name = "*.{pem,crt,ca,key}", fg = "#ff5555", bold = true, prefix = "󰌋 " }, - - # Improved size-based rules for media - { name = "*.{jpg,jpeg,png,gif}", size = "< 100KB", fg = "#8be9fd", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "< 1MB", fg = "#bd93f9", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "< 10MB", fg = "#ffb86c", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "> 10MB", fg = "#ff5555", prefix = "󰋯 " }, - - # Default Fallbacks - { name = "*", fg = "#f8f8f2" }, - { name = "*/", fg = "#bd93f9", bold = true, prefix = " " }, - - # Additional Development Files - { name = "*.{proto}", fg = "#bd93f9", italic = true, prefix = "󰯍 " }, - { name = "*.{graphql,gql}", fg = "#ff79c6", italic = true, prefix = "󰡷 " }, - { name = "*.{tf,tfvars}", fg = "#8be9fd", italic = true, prefix = "󱁢 " }, - - # Container and Cloud - { name = "*.{yaml,yml}", pattern = "^k8s|^kubernetes", fg = "#8be9fd", bold = true, prefix = "󱃾 " }, - { name = "*.{yaml,yml}", pattern = "^helm", fg = "#8be9fd", bold = true, prefix = "󰠿 " }, - - # Data Files - { name = "*.{csv,tsv}", fg = "#50fa7b", italic = true, prefix = "󰈛 " }, - { name = "*.{parquet,avro}", fg = "#bd93f9", italic = true, prefix = "󰋖 " }, - - # Size-based rules for documents - { name = "*.{pdf,epub,mobi}", size = "< 1MB", fg = "#8be9fd", prefix = "󰈙 " }, - { name = "*.{pdf,epub,mobi}", size = "< 10MB", fg = "#ffb86c", prefix = "󰈙 " }, - { name = "*.{pdf,epub,mobi}", size = "> 10MB", fg = "#ff5555", prefix = "󰈙 " }, - - # Additional Development Files - { name = "*.{sol}", fg = "#bd93f9", italic = true, prefix = "󰡪 " }, # Solidity files - { name = "*.{ex,exs}", fg = "#bd93f9", italic = true, prefix = "󰡁 " }, # Elixir files - { name = "*.{kt,kts}", fg = "#ff79c6", italic = true, prefix = "󱈙 " }, # Kotlin files - { name = "*.{swift}", fg = "#ff5555", italic = true, prefix = "󰛥 " }, # Swift files - - # Config Files - { name = "*.{nginx,nginx.conf}", fg = "#50fa7b", italic = true, prefix = "󰻭 " }, - { name = "*{webpack}*", fg = "#8be9fd", bold = true, prefix = "󰜫 " }, - - # ML/Data Science - { name = "*.{ipynb}", fg = "#ff79c6", italic = true, prefix = "󰠏 " }, - { name = "*.{pkl,pickle}", fg = "#50fa7b", italic = true, prefix = "󰜎 " }, - - # 3D/Graphics - { name = "*.{blend}", fg = "#ff79c6", italic = true, prefix = "󰂫 " }, - { name = "*.{fbx,obj,stl}", fg = "#8be9fd", italic = true, prefix = "󰆧 " }, - - # More granular size-based rules for media files - { name = "*.{jpg,jpeg,png,gif}", size = "< 50KB", fg = "#8be9fd", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "< 500KB", fg = "#bd93f9", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "< 2MB", fg = "#ffb86c", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "< 20MB", fg = "#ff7043", prefix = "󰋯 " }, - { name = "*.{jpg,jpeg,png,gif}", size = "> 20MB", fg = "#ff5555", prefix = "󰋯 " }, - - # Size categories for video files - { name = "*.{mp4,mkv,avi,mov}", size = "< 100MB", fg = "#8be9fd", prefix = "󰕧 " }, - { name = "*.{mp4,mkv,avi,mov}", size = "< 1GB", fg = "#ffb86c", prefix = "󰕧 " }, - { name = "*.{mp4,mkv,avi,mov}", size = "> 1GB", fg = "#ff5555", prefix = "󰕧 " }, -] - -# Keybindings -[keys] -# Visual key hints -show_hints = true -hint_style = { fg = "#6272a4", bg = "#44475a", italic = true } - -# Command palette -command_palette = { bg = "#282a36", fg = "#f8f8f2", selected_bg = "#44475a", selected_fg = "#f8f8f2", border = "#bd93f9" } - -# Preview -[preview] -tab_size = 2 -max_width = 120 -max_height = 60 -cache_dir = "/tmp/yazi" - -[preview.image] -enabled = true -format = "rgb" -max_width = 1920 -max_height = 1080 -quality = 90 -animate = true -cache = true - -[preview.preview_service] -image = "ueberzug" -video = "ffmpegthumbnailer" -pdf = "pdftoppm" -epub = "epub-thumbnailer" -office = "libreoffice --headless --convert-to pdf" -markdown = "glow" - -[preview.syntax] -theme = "Dracula" -background = "#282a36" - -# Opener -[opener] -edit = [ - { exec = 'nvim "$@"', desc = "Edit with Neovim" }, - { exec = 'code "$@"', desc = "Edit with VS Code" } -] -open = [ - { exec = 'xdg-open "$@"', desc = "Open with system default" }, - { exec = 'firefox "$@"', desc = "Open in Firefox" } -] -reveal = [ - { exec = 'nautilus "$@"', desc = "Reveal in file manager" } -] - -# Enhanced preview features -max_preview_size = 10485760 # 10MB limit for preview -scroll_offset = 5 -scroll_smooth = true diff --git a/yazi/.config/yazi/themes/gruvbox-mat.toml b/yazi/.config/yazi/themes/gruvbox-mat.toml deleted file mode 100644 index 6677c0e..0000000 --- a/yazi/.config/yazi/themes/gruvbox-mat.toml +++ /dev/null @@ -1,72 +0,0 @@ -# Gruvbox Material Dark theme for Yazi -# Based on https://github.com/sainnhe/gruvbox-material - -[manager] -cwd = { fg = "#d8a657" } # yellow - -# Hovered -hovered = { fg = "#282828", bg = "#a9b665" } # green background -preview_hovered = { underline = true } - -# Find -find_keyword = { fg = "#282828", bg = "#d8a657" } # yellow -find_position = { fg = "#282828", bg = "#7daea3" } # aqua - -# Marker -marker_copied = { fg = "#a9b665", bg = "#a9b665" } # green -marker_cut = { fg = "#ea6962", bg = "#ea6962" } # red -marker_marked = { fg = "#7daea3", bg = "#7daea3" } # aqua -marker_selected = { fg = "#d8a657", bg = "#d8a657" } # yellow - -# Tab -tab_active = { fg = "#282828", bg = "#a9b665" } # green -tab_inactive = { fg = "#d4be98", bg = "#3c3836" } # fg on bg1 -tab_width = 1 - -# Count -count_copied = { fg = "#282828", bg = "#a9b665" } # green -count_cut = { fg = "#282828", bg = "#ea6962" } # red -count_selected = { fg = "#282828", bg = "#7daea3" } # aqua - -# Border -border_symbol = "│" -border_style = { fg = "#504945" } # bg2 - -# Syntect theme for preview -syntect_theme = "~/.config/yazi/Gruvbox-Material-Dark.tmTheme" - -[status] -separator_open = "" -separator_close = "" -separator_style = { fg = "#504945", bg = "#504945" } # bg2 - -# Mode -mode_normal = { fg = "#282828", bg = "#7daea3", bold = true } # aqua -mode_select = { fg = "#282828", bg = "#d8a657", bold = true } # yellow -mode_unset = { fg = "#282828", bg = "#ea6962", bold = true } # red - -# Progress -progress_label = { fg = "#d4be98", bold = true } # fg -progress_normal = { fg = "#7daea3", bg = "#3c3836" } # aqua on bg1 -progress_error = { fg = "#ea6962", bg = "#3c3836" } # red on bg1 - -# Permissions -permissions_t = { fg = "#a9b665" } # green -permissions_r = { fg = "#d8a657" } # yellow -permissions_w = { fg = "#ea6962" } # red -permissions_x = { fg = "#7daea3" } # aqua -permissions_s = { fg = "#504945" } # bg2 - -[input] -border = { fg = "#7daea3" } # aqua -title = { fg = "#d4be98" } # fg -value = { fg = "#d4be98" } # fg -selected = { reversed = true } - -[select] -border = { fg = "#7daea3" } # aqua -active = { fg = "#d8a657" } # yellow -inactive = { fg = "#7c6f64" } # bg3 - -[completion] -border = { fg = "#7daea3" } # aqua diff --git a/yazi/.config/yazi/themes/rose.toml b/yazi/.config/yazi/themes/rose.toml deleted file mode 100644 index 4f3436f..0000000 --- a/yazi/.config/yazi/themes/rose.toml +++ /dev/null @@ -1,4 +0,0 @@ -[flavor] -dark = "rose-pine-moon" -# or "rose-pine-moon" -# or light = "rose-pine-dawn"