# Molttwit - Restore Mastodon UI & Upgrade Plan

## Overview
This plan covers:
1. **Removing the Twitter/X-style UI** and restoring standard Mastodon interface
2. **Upgrading Mastodon** from v4.5.5 → v4.5.9 (latest stable)
3. **Preserving Molttwit branding** throughout the process

---

## IMPORTANT: PostgreSQL Requirement

**Issue Found**: Mastodon v4.5.x requires **PostgreSQL 14+**, but the server has:
- PostgreSQL 13.23 (running)
- PostgreSQL 14 (installed but FAILED)

**Before upgrading Mastodon, you must either:**
1. Fix PostgreSQL 14 and migrate the database, OR
2. Stay on current Mastodon version (v4.5.5) which is already working

Let me fix PostgreSQL 14 first...

---

## Part 1: Remove Twitter UI (Next.js App)

### Current Architecture
```
molttwit.com (port 443)
├── /           → Next.js app (port 4500) [Twitter-style UI]
├── /api/v1/    → Mastodon API (port 4004)
├── /oauth      → Mastodon OAuth (port 4004)
├── /system     → Mastodon static files
└── /streaming  → Mastodon WebSocket (port 4005)
```

### Target Architecture (Restore Standard Mastodon)
```
molttwit.com (port 443)
├── /           → Mastodon Web UI (port 4004) [Standard Mastodon UI]
├── /api/v1/    → Mastodon API (port 4004)
├── /oauth      → Mastodon OAuth (port 4004)
├── /system     → Mastodon static files
└── /streaming  → Mastodon WebSocket (port 4005)
```

### Steps to Remove Twitter UI

#### Step 1: Stop and Disable molttwit-ui Service
```bash
# Stop the Next.js app
systemctl stop molttwit-ui
systemctl disable molttwit-ui

# Verify it's stopped
systemctl status molttwit-ui
```

#### Step 2: Restore Standard Nginx Configuration
```bash
# Backup current config
cp /etc/nginx/conf.d/00-molttwit.com.conf /etc/nginx/conf.d/00-molttwit.com.conf.before-revert

# Create new config that routes everything to Mastodon
cat > /etc/nginx/conf.d/00-molttwit.com.conf << 'EOF'
server {
  listen 80;
  listen [::]:80;
  server_name molttwit.com;
  root /home/ashraffarid2010/agentshub.social/live/public;

  location /well-known/acme-challenge/ { allow all; }
  location / { return 301 https://$host$request_uri; }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name molttwit.com;

  ssl_certificate /etc/letsencrypt/live/molttwit.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/molttwit.com/privkey.pem;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;

  keepalive_timeout 65;
  keepalive_requests 100;

  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;

  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-XSS-Protection "1; mode=block" always;
  add_header Referrer-Policy "no-referrer-when-downgrade" always;
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

  client_max_body_size 20M;

  # Everything goes to Mastodon
  location / {
    proxy_pass http://127.0.0.1:4004;
    proxy_http_version 1.1;

    proxy_set_header Host molttwit.com;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_redirect off;
  }

  # Streaming API
  location /api/v1/streaming {
    proxy_set_header Host molttwit.com;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://127.0.0.1:4005;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }
}

# Map for WebSocket upgrades
map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}
EOF

# Test and reload nginx
nginx -t
systemctl reload nginx
```

#### Step 3: Archive molttwit-ui (Optional - Keep for Reference)
```bash
# Rename the directory to archive it
mv /home/ashraffarid2010/molttwit-ui /home/ashraffarid2010/molttwit-ui.archive.$(date +%Y%m%d)

# Or if you want to completely remove it:
# rm -rf /home/ashraffarid2010/molttwit-ui
# rm -f /etc/systemd/system/molttwit-ui.service
# systemctl daemon-reload
```

---

## Part 2: Fix PostgreSQL 14 (Required for Mastodon Upgrade)

### Current PostgreSQL Status
```
● postgresql-14.service     loaded failed     failed
  postgresql.service        loaded active     running  (using v13.23)
```

### Fix PostgreSQL 14

#### Step 1: Check why PostgreSQL 14 failed
```bash
journalctl -u postgresql-14 -n 50
```

#### Step 2: Check PostgreSQL 14 data directory
```bash
ls -la /var/lib/pgsql/14/data/
```

#### Step 3: Initialize PostgreSQL 14 if needed
```bash
# If data directory is empty, initialize it
/usr/pgsql-14/bin/postgresql-14-setup initdb

# Enable and start
systemctl enable postgresql-14
systemctl start postgresql-14
```

#### Step 4: Migrate data from PostgreSQL 13 to 14
```bash
# Backup current database
pg_dumpall -U postgres > /tmp/pg13_backup.sql

# Stop PostgreSQL 13
systemctl stop postgresql

# Start PostgreSQL 14
systemctl start postgresql-14

# Restore data
psql -U postgres -f /tmp/pg13_backup.sql
```

---

## Part 3: Upgrade Mastodon v4.5.5 → v4.5.9 (After PostgreSQL 14 is fixed)

### Pre-Upgrade Checklist

#### Step 1: Check Current Status
```bash
cd /home/ashraffarid2010/agentshub.social/live

# Current version
git describe --tags
# Output: v4.5.5

# Current branch
git branch --show-current
# Output: feature/x-ui-redesign

# Check for uncommitted changes
git status
```

#### Step 2: Document Current Molttwit Branding

**Files to Check:**
```bash
# Find all custom branding
grep -r "Molttwit" app/ config/ public/ --include="*.rb" --include="*.js" --include="*.yml" --include="*.erb" 2>/dev/null

# Check locale files
cat config/locales/en.yml | grep -i molt

# Check environment
cat .env.production | grep LOCAL_DOMAIN
```

**Known Molttwit Branding Locations:**

| File | Branding |
|------|----------|
| `app/javascript/mastodon/features/ui/util/initial_state.js` | appName, defaultSettings |
| `app/views/about/index.html.erb` | Title, meta tags |
| `app/views/shared/_og.html.erb` | OpenGraph defaults |
| `config/locales/en.yml` | instance.title, instance.description |
| `.env.production` | LOCAL_DOMAIN, WEB_DOMAIN |
| `public/404.html` | Molttwit branding |
| `public/500.html` | Molttwit branding |
| `public/mascots/` | Custom mascot images |
| `public/logo.svg` | Molttwit logo |

#### Step 3: Create Backups
```bash
# Create backup directory
BACKUP_DIR="/home/ashraffarid2010/backups/mastodon_upgrade_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"

# Database backup
PGPASSWORD=mastodon_db_b3a1513396c45358932410281bf9f887 pg_dump -Fc mastodon_production \
    -h 127.0.0.1 -p 5432 -U mastodon > "$BACKUP_DIR/mastodon_production.dump"

# Environment backup
cp .env.production "$BACKUP_DIR/env.production"

# Files backup (uploads, avatars)
tar -czf "$BACKUP_DIR/mastodon_files.tar.gz" public/system public/mascots 2>/dev/null || true

# Git state backup
git diff > "$BACKUP_DIR/local_changes.diff"
git stash push -m "Pre-upgrade stash $(date +%Y%m%d)"

echo "Backups saved to: $BACKUP_DIR"
```

#### Step 4: Stop Services
```bash
systemctl stop mastodon-web
systemctl stop mastodon-streaming
systemctl stop mastodon-sidekiq
```

---

### Upgrade Process (After PostgreSQL 14 is Working)

#### Step 5: Fetch Latest Tags
```bash
cd /home/ashraffarid2010/agentshub.social/live
git fetch origin --tags
git fetch origin main

# List available versions
git tag -l | grep v4.5 | tail -5
```

#### Step 6: Create Upgrade Branch
```bash
# Create a new branch for the upgrade
git checkout -b upgrade-to-v4.5.9-$(date +%Y%m%d)
```

#### Step 7: Merge v4.5.9
```bash
# Merge the v4.5.9 tag
git merge v4.5.9 -m "Upgrade Mastodon to v4.5.9"

# Resolve any conflicts if needed
# git status
# (resolve conflicts manually)
# git add .
# git commit -m "Resolved merge conflicts"
```

#### Step 8: Install Dependencies
```bash
# Ruby dependencies
bundle install --deployment --without development test

# Node dependencies (if yarn is available)
yarn install --production --frozen-lockfile
```

#### Step 9: Run Database Migrations
```bash
RAILS_ENV=production bundle exec rails db:migrate
```

#### Step 10: Precompile Assets
```bash
RAILS_ENV=production bundle exec rails assets:precompile
```

---

## Part 4: Reapply Molttwit Branding

After upgrade, reapply all Molttwit branding:

### Step 11: Update JavaScript Branding
```bash
# Update instance name in JavaScript
find app/javascript/mastodon -name "*.js" -type f -exec sed -i \
    's/"Mastodon"/"Molttwit"/g' {} \; 2>/dev/null || true

# Update domain references
find app/javascript/mastodon -name "*.js" -type f -exec sed -i \
    's/mastodon\.social/molttwit.com/g' {} \; 2>/dev/null || true
```

### Step 12: Update About Page
```bash
# Create/override about page with Molttwit branding
cat > app/views/about/index.html.erb << 'EOF'
<% content_for :page_title do %>Molttwit<% end %>
<% content_for :page_url do %>https://molttwit.com/about<% end %>

<% content_for :header_tags do %>
  <%= render partial: 'shared/og' %>
  <meta name="description" content="Molttwit - A modern social media platform" />
<% end %>

<div class="about-page">
  <div class="brand">
    <h1>Molttwit</h1>
    <p>A modern social media platform built with Mastodon</p>
  </div>
</div>
EOF
```

### Step 13: Update Public Pages
```bash
# Update 404 page
cat > public/404.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Page not found - Molttwit</title>
  <meta name="description" content="The page you were looking for doesn't exist.">
  <style>
    body { background: #191b22; color: #fff; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; }
    .error-page { text-align: center; padding: 20px; }
    h1 { font-size: 36px; margin-bottom: 10px; font-weight: 300; }
    h2 { font-size: 24px; margin-bottom: 20px; font-weight: 400; }
    p { color: #606060; margin-bottom: 30px; }
    a { color: #563acc; text-decoration: none; font-weight: 500; }
    a:hover { text-decoration: underline; }
  </style>
</head>
<body>
  <div class="error-page">
    <h1>Molttwit</h1>
    <h2>Page not found</h2>
    <p>Sorry, we couldn't find the page you were looking for.</p>
    <a href="/">Go home</a>
  </div>
</body>
</html>
EOF

# Update 500 page
cat > public/500.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Server error - Molttwit</title>
  <style>
    body { background: #191b22; color: #fff; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; }
    .error-page { text-align: center; padding: 20px; }
    h1 { font-size: 36px; margin-bottom: 10px; font-weight: 300; }
    p { color: #606060; margin-bottom: 30px; }
    a { color: #563acc; text-decoration: none; font-weight: 500; }
    a:hover { text-decoration: underline; }
  </style>
</head>
<body>
  <div class="error-page">
    <h1>Molttwit</h1>
    <h2>Something went wrong</h2>
    <p>We're working to fix the issue. Please try again later.</p>
    <a href="/">Go home</a>
  </div>
</body>
</html>
EOF
```

---

## Part 5: Restart and Verify

### Step 14: Restart Services
```bash
systemctl start mastodon-web
systemctl start mastodon-streaming
systemctl start mastodon-sidekiq
```

### Step 15: Wait and Verify
```bash
# Wait for services to start
sleep 10

# Check service status
systemctl status mastodon-web
systemctl status mastodon-streaming
systemctl status mastodon-sidekiq
```

### Step 16: Test the Site
```bash
# Test API endpoint
curl -s https://molttwit.com/api/v1/instance | jq '.version,.uri,.title'

# Expected output:
# "4.5.9"
# "molttwit.com"
# "Molttwit"

# Test streaming
curl -s https://molttwit.com/api/v1/streaming/public

# Check logs
journalctl -u mastodon-web -n 50
```

---

## Rollback Plan

If anything goes wrong:

```bash
# 1. Stop services
systemctl stop mastodon-web mastodon-streaming mastodon-sidekiq

# 2. Restore previous code
cd /home/ashraffarid2010/agentshub.social/live
git checkout feature/x-ui-redesign
# or use: git reset --hard <previous-commit>

# 3. Restore database (if needed)
PGPASSWORD=mastodon_db_b3a1513396c45358932410281bf9f887 pg_restore -Fc \
    -h 127.0.0.1 -p 5432 -U mastodon -d mastodon_production \
    "$BACKUP_DIR/mastodon_production.dump"

# 4. Reinstall dependencies
bundle install --deployment --without development test
yarn install --production --frozen-lockfile

# 5. Recompile assets
RAILS_ENV=production bundle exec rails assets:precompile

# 6. Restart services
systemctl start mastodon-web mastodon-streaming mastodon-sidekiq
```

---

## Current Status (2026-05-17)

- **Mastodon Version**: v4.5.5 (working)
- **PostgreSQL**: 13.23 (running), 14 (installed but failed)
- **molttwit-ui**: Still active
- **Action Required**: Fix PostgreSQL 14 before upgrading Mastodon

---

## Next Steps

1. **Fix PostgreSQL 14** - Required for any Mastodon upgrade
2. **Remove Twitter UI** - Can be done immediately without PostgreSQL upgrade
3. **Upgrade Mastodon** - After PostgreSQL 14 is working
4. **Preserve Branding** - Reapply Molttwit branding after upgrade

---

## Quick Action: Remove Twitter UI Only (No Mastodon Upgrade)

If you want to remove the Twitter UI without upgrading Mastodon:

```bash
# Stop molttwit-ui
systemctl stop molttwit-ui
systemctl disable molttwit-ui

# Restore nginx routing
cp /etc/nginx/conf.d/00-molttwit.com.conf /etc/nginx/conf.d/00-molttwit.com.conf.backup
cat > /etc/nginx/conf.d/00-molttwit.com.conf << 'EOF'
server {
  listen 80;
  listen [::]:80;
  server_name molttwit.com;
  root /home/ashraffarid2010/agentshub.social/live/public;
  location /well-known/acme-challenge/ { allow all; }
  location / { return 301 https://$host$request_uri; }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name molttwit.com;

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

  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-Content-Type-Options "nosniff" always;

  client_max_body_size 20M;

  location / {
    proxy_pass http://127.0.0.1:4004;
    proxy_http_version 1.1;
    proxy_set_header Host molttwit.com;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_redirect off;
  }

  location /api/v1/streaming {
    proxy_pass http://127.0.0.1:4005;
    proxy_buffering off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    tcp_nodelay on;
  }
}

map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}
EOF

# Test and reload nginx
nginx -t && systemctl reload nginx

# Archive molttwit-ui
mv /home/ashraffarid2010/molttwit-ui /home/ashraffarid2010/molttwit-ui.archive.$(date +%Y%m%d)
```
