# PhotoHost — Фото-хостинг Современный фото-хостинг на **Python (Flask)**, **PostgreSQL** и **Docker Compose**. - Красивая главная страница с drag-and-drop загрузкой - **Регистрация и авторизация** пользователей - **Личный кабинет** — загрузка и управление своими фото - **Админ-панель** — пользователи, фото, статистика - **Автоматическое создание первого администратора** через `.env` - Галерея загруженных фото - Копирование прямых ссылок на изображения - Хранение метаданных в PostgreSQL, файлов — в Docker volume --- ## Структура проекта ``` fotohost/ ├── app/ │ ├── __init__.py # Flask-приложение, Flask-Login │ ├── models.py # User, Photo │ ├── auth.py # Регистрация, вход, выход │ ├── routes.py # Главная, загрузка, личный кабинет │ ├── admin.py # Админ-панель │ ├── bootstrap.py # Миграция схемы, первый admin │ ├── auth_utils.py # Декораторы доступа │ ├── templates/ # HTML-шаблоны │ └── static/ # CSS и JavaScript ├── uploads/ # Локальная папка (в Docker — volume) ├── docker-compose.yml # Оркестрация web + PostgreSQL ├── Dockerfile ├── wsgi.py # Точка входа для Gunicorn ├── requirements.txt ├── .env.example └── README.md ``` --- ## Развёртывание на Ubuntu 24.04 Подробная пошаговая инструкция для чистого сервера Ubuntu 24.04 LTS. ### 1. Подключение к серверу ```bash ssh user@YOUR_SERVER_IP ``` Замените `user` на имя пользователя и `YOUR_SERVER_IP` на IP-адрес сервера. ### 2. Обновление системы ```bash sudo apt update && sudo apt upgrade -y ``` ### 3. Установка необходимых пакетов ```bash sudo apt install -y ca-certificates curl gnupg git ``` ### 4. Установка Docker Docker официально поддерживается на Ubuntu 24.04. ```bash # Добавить GPG-ключ Docker sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg # Добавить репозиторий Docker echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # Установить Docker Engine и Compose plugin sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ``` Проверка установки: ```bash sudo docker run hello-world docker compose version ``` ### 5. Добавить пользователя в группу docker (опционально) Чтобы не использовать `sudo` перед каждой командой docker: ```bash sudo usermod -aG docker $USER newgrp docker ``` ### 6. Копирование проекта на сервер **Вариант A — через Git:** ```bash cd ~ git clone https://git.evilfox.cc/test2/fotohost.git fotohost cd fotohost ``` **Вариант B — через SCP с локального компьютера:** ```bash # Выполнить на локальной машине (Windows PowerShell / Linux) scp -r ./fotohost user@YOUR_SERVER_IP:~/ ``` ```bash # На сервере cd ~/fotohost ``` **Вариант C — создать файлы вручную** — скопируйте содержимое проекта в каталог `~/fotohost`. ### 7. Настройка переменных окружения ```bash cp .env.example .env nano .env ``` Измените значения в `.env`: ```env POSTGRES_USER=photohost POSTGRES_PASSWORD=YOUR_STRONG_DB_PASSWORD POSTGRES_DB=photohost DATABASE_URL=postgresql://photohost:YOUR_STRONG_DB_PASSWORD@db:5432/photohost SECRET_KEY=random_string_min_32_chars MAX_UPLOAD_MB=10 APP_PORT=8080 # Первый администратор (создаётся автоматически при первом запуске) ADMIN_USERNAME=admin ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=YOUR_STRONG_ADMIN_PASSWORD ``` Сгенерировать случайный `SECRET_KEY`: ```bash python3 -c "import secrets; print(secrets.token_hex(32))" ``` > **Первый администратор:** при первом запуске, если в базе нет ни одного admin, создаётся пользователь из `ADMIN_USERNAME` / `ADMIN_EMAIL` / `ADMIN_PASSWORD`. Обязательно смените пароль в `.env` до деплоя. Альтернатива — создать admin вручную через CLI: ```bash docker compose exec web flask create-admin ``` ### 8. Запуск приложения ```bash docker compose up -d --build ``` Проверка статуса контейнеров: ```bash docker compose ps ``` Ожидаемый результат — оба сервиса `running`: | Сервис | Контейнер | Порт | |--------|----------------|-------------| | web | photohost-web | 8080 → 8000 | | db | photohost-db | 5432 (внутр.) | Просмотр логов: ```bash docker compose logs -f web ``` ### 9. Проверка работы Откройте в браузере: ``` http://YOUR_SERVER_IP:8080 ``` Загрузите тестовое изображение — оно должно появиться в галерее. Войдите как admin (`/auth/login`) → откройте **Админку** (`/admin`). ### 10. Открытие порта в файрволе (UFW) Если включён UFW: ```bash sudo ufw allow 8080/tcp sudo ufw allow OpenSSH sudo ufw enable sudo ufw status ``` ### 11. Автозапуск при перезагрузке сервера Docker Compose с `restart: unless-stopped` уже перезапускает контейнеры. Убедитесь, что Docker включён: ```bash sudo systemctl enable docker sudo systemctl start docker ``` --- ## Регистрация, авторизация и роли | URL | Описание | |-----|----------| | `/auth/register` | Регистрация нового пользователя | | `/auth/login` | Вход (логин или email) | | `/auth/logout` | Выход | | `/cabinet/` | Личный кабинет — мои фото | | `/cabinet/profile` | Настройки профиля, смена пароля | | `/admin/` | Панель администратора (только admin) | | `/admin/users` | Управление пользователями | | `/admin/photos` | Все фото на сервере | **Права доступа:** - Загрузка фото — только авторизованным пользователям - Удаление фото — владелец или администратор - Админка — только пользователи с `is_admin=True` --- ## Полезные команды | Действие | Команда | |-----------------------|----------------------------------| | Остановить | `docker compose down` | | Перезапустить | `docker compose restart` | | Пересобрать | `docker compose up -d --build` | | Логи web | `docker compose logs -f web` | | Логи БД | `docker compose logs -f db` | | Зайти в контейнер web | `docker compose exec web bash` | | Зайти в PostgreSQL | `docker compose exec db psql -U photohost -d photohost` | --- ## Резервное копирование ### База данных ```bash docker compose exec db pg_dump -U photohost photohost > backup_$(date +%Y%m%d).sql ``` Восстановление: ```bash cat backup_20250606.sql | docker compose exec -T db psql -U photohost -d photohost ``` ### Загруженные фото Фото хранятся в Docker volume `uploads_data`. Список volumes: ```bash docker volume ls ``` Бэкап volume: ```bash docker run --rm -v photohost_uploads_data:/data -v $(pwd):/backup alpine tar czf /backup/uploads_backup.tar.gz -C /data . ``` --- ## Настройка домена и HTTPS (Nginx + Let's Encrypt) ### Установка Nginx и Certbot ```bash sudo apt install -y nginx certbot python3-certbot-nginx ``` ### Конфиг Nginx ```bash sudo nano /etc/nginx/sites-available/photohost ``` ```nginx server { listen 80; server_name photos.example.com; client_max_body_size 15M; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` ```bash sudo ln -s /etc/nginx/sites-available/photohost /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` ### SSL-сертификат ```bash sudo certbot --nginx -d photos.example.com ``` Откройте порты 80 и 443: ```bash sudo ufw allow 'Nginx Full' ``` --- ## Локальная разработка (без Docker) ```bash # Установить PostgreSQL локально или запустить только БД: docker compose up -d db python3 -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install -r requirements.txt cp .env.example .env # Измените DATABASE_URL на localhost: # DATABASE_URL=postgresql://photohost:photohost_secret@localhost:5432/photohost export FLASK_APP=wsgi.py python wsgi.py ``` Приложение будет доступно на `http://localhost:8000`. > Для локального запуска только БД добавьте в `docker-compose.yml` для сервиса `db` строку `ports: - "5432:5432"`. --- ## API | Метод | URL | Описание | |-------|---------------|-----------------------------| | GET | `/` | Главная страница | | POST | `/auth/register` | Регистрация | | POST | `/auth/login` | Вход | | GET | `/cabinet/` | Личный кабинет | | GET | `/admin/` | Админ-панель | | POST | `/upload` | Загрузка фото (auth) | | GET | `/uploads/` | Прямая ссылка на файл | | GET | `/api/photos` | JSON-список всех фото | | POST | `/delete/` | Удаление фото | Пример ответа `/api/photos`: ```json [ { "id": 1, "url": "/uploads/abc123.jpg", "original_name": "photo.jpg", "file_size": 245760, "size_human": "240.0 КБ", "created_at": "2025-06-06T12:00:00+00:00" } ] ``` --- ## Устранение неполадок **Контейнер web не запускается** ```bash docker compose logs web ``` Частая причина — БД ещё не готова. Healthcheck в `docker-compose.yml` решает это; подождите 30 секунд и перезапустите: ```bash docker compose restart web ``` **Ошибка подключения к PostgreSQL** Проверьте, что пароли в `.env` совпадают в `POSTGRES_PASSWORD` и `DATABASE_URL`. **Фото не загружаются (413 Request Entity Too Large)** Увеличьте `MAX_UPLOAD_MB` в `.env` и `client_max_body_size` в Nginx. **Порт 8080 занят** Измените `APP_PORT=9090` в `.env` и перезапустите: ```bash docker compose down && docker compose up -d ``` --- ## Технологии - Python 3.12, Flask 3, Flask-Login, Gunicorn - PostgreSQL 16 - SQLAlchemy, Pillow - Docker & Docker Compose