Какой сервис выбрать первым для self-hosting: полное руководство для начинающих

Подробное руководство о выборе первого сервиса для самостоятельного размещения. Анализ популярных вариантов, факторы выбора и практические примеры для новичков в homelab.

Не указано

Подготовка инфраструктуры

Выбор облачного провайдера, создание сервера, базовая настройка, создание пользователя и настройка безопасности.

# Обновление системы
apt update && apt upgrade -y

# Установка необходимых компонентов
apt install -y nginx git curl htop unzip

# Настройка файрвола
ufw allow ssh
ufw allow http
ufw allow https
ufw enable

Установка Node.js

Установка Node.js с помощью Node Version Manager (nvm) для управления версиями.

# Установка nvm (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

# Загрузка nvm
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \."$NVM_DIR/nvm.sh"

# Установка последней LTS версии
nvm install --lts

Установка базы данных MongoDB

Установка и настройка MongoDB в качестве базы данных для приложения.

# Импорт ключей репозитория
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add -

# Добавление репозитория
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list

# Установка и запуск
apt update
apt install -y mongodb-org
systemctl start mongod
systemctl enable mongod

Настройка приложения

Создание директории, клонирование репозитория и установка зависимостей.

# Создание директории и клонирование репозитория
sudo -u deployer mkdir -p /var/www/blog
cd /var/www/blog
sudo -u deployer git clone https://github.com/username/blog-repo .

# Установка зависимостей
sudo -u deployer npm install --production

# Создание конфигурации
sudo -u deployer nano .env

Настройка PM2

Настройка PM2 для управления процессами Node.js в продакшене.

module.exports = {
  apps: [{
    name: 'blog',
    script: 'app.js',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production',
      PORT: 3000
    },
    error_file: '/var/log/blog/error.log',
    out_file: '/var/log/blog/out.log',
    log_file: '/var/log/blog/combined.log',
    time: true
  }]
};

Настройка Nginx

Настройка Nginx как reverse proxy для Node.js приложения с оптимизацией производительности.

server {
    listen 80;
    server_name your_domain.com www.your_domain.com;
    root /var/www/blog/public;
    index index.html;

    # Оптимизация производительности
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_proxied any;
    gzip_comp_level 6;
    
    # Кэширование статики
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
        expires 7d;
        add_header Cache-Control "public, no-transform";
        access_log off;
    }

    # API-запросы
    location /api {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    # Остальные запросы
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Настройка CI/CD с GitHub Actions

Автоматизация развертывания с помощью GitHub Actions.

name: Deploy to Production

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
      
    - name: Build app
      run: npm run build
      
    - name: Deploy to server
      uses: appleboy/scp-action@master
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        source: "dist/"
        target: "/var/www/blog"
        
    - name: Restart application
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          cd /var/www/blog
          pm2 restart blog

Настройка SSL-сертификата

Установка и настройка SSL-сертификата с помощью Certbot.

# Установка Certbot
apt install -y certbot python3-certbot-nginx

# Получение сертификата
certbot --nginx -d your_domain.com -d www.your_domain.com

Резервное копирование

Создание и настройка скрипта автоматического резервного копирования.

#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/var/backups/blog"
APP_DIR="/var/www/blog"
MONGO_USER="mongo_user"
MONGO_PASS="mongo_password"

# Создание директорий
mkdir -p $BACKUP_DIR

# Создание бэкапа кода приложения
tar -czf $BACKUP_DIR/app_$DATE.tar.gz -C $APP_DIR .

# Создание бэкапа базы данных
mongodump --username $MONGO_USER --password $MONGO_PASS --db blog --out $BACKUP_DIR/mongo_$DATE

# Компрессия бэкапа БД
tar -czf $BACKUP_DIR/mongo_$DATE.tar.gz -C $BACKUP_DIR mongo_$DATE
rm -rf $BACKUP_DIR/mongo_$DATE

# Удаление бэкапов старше 7 дней
find $BACKUP_DIR -type f -mtime +7 -delete

Оптимизация производительности

Настройка Redis для кеширования и оптимизация изображений с помощью Sharp.

const redis = require('redis');
const client = redis.createClient();

// Middleware для кеширования
app.get('/api/posts', async (req, res) => {
  const cacheKey = 'all_posts';
  
  // Попытка получить из кеша
  client.get(cacheKey, async (err, reply) => {
    if (reply) {
      return res.json(JSON.parse(reply));
    }
    
    // Если в кеше нет, получить из БД
    try {
      const posts = await Post.find();
      // Сохранение в кеш на 1 час
      client.setex(cacheKey, 3600, JSON.stringify(posts));
      res.json(posts);
    } catch (err) {
      res.status(500).json({ message: 'Server error' });
    }
  });
});