Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

TechCorp Linux System Administration

Финальный проект курса «Сетевые системы и приложения»

Ubuntu Python Docker Nginx 8 parts 8 screenshots

Практическое задание: развернуть и сопровождать Ubuntu Server
как Linux System Administrator в компании TechCorp


О задании

Цель Развернуть и сопровождать production-like сервер TechCorp
Результат Ubuntu Server + TCP Echo + Docker + Nginx + Flask + UFW + cron
Отчёт 8 скриншотов + PDF с пояснениями
Срок 1 неделя

Быстрый старт

  1. Создайте VM Ubuntu Server 24.04 в VirtualBox (NAT + Host-only).
  2. Выполняйте Части 1 → 8 по порядку, отмечая прогресс ниже.

Навигация

Подготовка Части задания Завершение
Как читать 1 · Сеть и SSH Сдача работы
Архитектура 2 · Users и права Устранение неполадок
Подготовка VM 3 · TCP Echo Справочник sysadmin
Прогресс 4 · Мониторинг Навыки для резюме
5 · Docker Лицензия
6 · Nginx и Flask
7 · Безопасность
8 · Логи и cron

Как читать этот документ

Метка Назначение
ТЕОРИЯ Зачем это нужно sysadmin-у
ШАГ N.M Конкретное действие
ФАЙЛ Код (нажмите, чтобы развернуть)
ПОДСКАЗКА Типичные ошибки
ПРОВЕРКА Чеклист перед переходом дальше
СКРИНШОТ Что сдать в отчёт

Выполняйте части 1 → 8 строго по порядку.
Ошибка? → Устранение неполадок


Прогресс выполнения

  • Часть 1 Сеть и SSH · Скриншот №1
  • Часть 2 Пользователи и права · Скриншот №2
  • Часть 3 TCP Echo Server · Скриншот №3
  • Часть 4 Мониторинг · Скриншот №4
  • Часть 5 Docker · Скриншот №5
  • Часть 6 Nginx и Flask · Скриншот №6
  • Часть 7 Безопасность · Скриншот №7
  • Часть 8 Логи и cron · Скриншот №8

Архитектура сервера

flowchart LR
    subgraph pc [Windows PC]
        SSH_Client[SSH Client]
    end

    subgraph vm [Ubuntu 192.168.56.10]
        SSH[":22 SSH"]
        NGX[Nginx]
        DKR[Docker]
        TCP["tcp-server :5000"]
        WEB["flask-server :5002"]
        UFW[UFW Firewall]
    end

    SSH_Client -->|SSH| SSH
    SSH_Client -->|TCP :5001| UFW
    SSH_Client -->|HTTP :8080| UFW
    UFW --> NGX
    NGX -->|stream| TCP
    NGX -->|http| WEB
    DKR --- TCP
    DKR --- WEB
Loading

Карта портов

Порт Сервис Снаружи
22 SSH да
5000 TCP Echo (Docker) нет
5001 Nginx → TCP Echo да
5002 Flask (Docker) нет
8080 Nginx → Flask да

На порту 5000 только один процесс (Python или Docker).

Структура файлов на сервере

/opt/tcp_echo/
├── Server_Socket/server.py
├── Client_Socket/client.py
├── flask_app/app.py
├── flask_app/requirements.txt
├── scripts/status.sh, backup.sh
├── logs/  config/  backups/
├── .env
├── Dockerfile
└── Dockerfile.flask

Подготовка VM

Параметр Значение
RAM 4 GB · CPU 2 · Disk 200 GB
Сеть 1 NAT (интернет)
Сеть 2 Host-only (Windows ↔ VM)
Hostname techcorp-srv01
Пользователь admin

При установке Ubuntu включите OpenSSH server.

# Задать имя сервера (видно в логах и status.sh)
sudo hostnamectl set-hostname techcorp-srv01

# Проверить версии инструментов
python3 --version    # нужен Python 3.10+
git --version


ЧАСТЬ 1 · Сеть и SSH

Скриншот №1 ip addr show enp0s8 + systemctl status ssh

ТЕОРИЯ

Компонент Назначение
enp0s3 (NAT) Интернет обновления, Docker pull
enp0s8 (Host-only) Статический IP 192.168.56.10 доступ с Windows
SSH (:22) Удалённое администрирование

ШАГ 1.1 · Инвентаризация

# link  состояние интерфейса (UP/DOWN)
ip link show

# addr  назначенные IP-адреса
ip addr show

ШАГ 1.2 · Netplan (статический IP)

# Host-only адаптер должен быть UP до применения netplan
sudo ip link set enp0s8 up

sudo nano /etc/netplan/00-installer-config.yaml
ФАЙЛ · /etc/netplan/00-installer-config.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s8:
      dhcp4: no                              # статический IP, не DHCP
      addresses: [192.168.56.10/24]        # /24 = маска 255.255.255.0
sudo netplan apply

# Проверка: IP 192.168.56.10, state UP
ip addr show enp0s8

# Связь с Windows-хостом VirtualBox
ping -c 3 192.168.56.1

# Интернет через NAT-адаптер enp0s3
ping -c 3 8.8.8.8

ШАГ 1.3 · SSH

sudo apt update && sudo apt upgrade -y
sudo apt install openssh-server -y

# enable  автозапуск SSH при загрузке
sudo systemctl enable ssh
sudo systemctl status ssh
# Подключение с Windows PowerShell
ssh admin@192.168.56.10

ПОДСКАЗКА

  • enp0s8 DOWN → sudo ip link set enp0s8 up до netplan apply
  • ping fail → VirtualBox → Host Network Manager
  • IP Windows → ipconfig (обычно 192.168.56.1)

ПРОВЕРКА

  • IP 192.168.56.10, интерфейс UP
  • ping хоста и 8.8.8.8 успешен
  • SSH active, вход с Windows работает


ЧАСТЬ 2 · Пользователи, sudo и права

Скриншот №2 groups alex + ls -la /opt/tcp_echo

ТЕОРИЯ

Понятие Смысл
User Личный аккаунт сотрудника
Group Общие права (devops, developers)
chmod 750 rwx для владельца и группы, остальным нет
chmod 700 Только владелец (логи, секреты)
sudo Выполнение от root с ограничениями

ШАГ 2.1 · Пользователи

sudo groupadd devops
sudo groupadd developers

# -m создаёт /home, -G добавляет в группу, -s задаёт shell
sudo useradd -m -G devops -s /bin/bash alex
sudo useradd -m -G developers -s /bin/bash maria
sudo useradd -m -s /bin/bash john

sudo passwd alex
sudo passwd maria
sudo passwd john

groups alex    # ожидаем: alex devops
groups maria   # ожидаем: maria developers

ШАГ 2.2 · sudo для devops

# visudo проверяет синтаксис  безопаснее прямого редактирования
sudo visudo -f /etc/sudoers.d/devops
ФАЙЛ · /etc/sudoers.d/devops
# Группа devops: перезапуск служб и скрипты без пароля root
%devops ALL=(ALL) NOPASSWD: /bin/systemctl restart tcp-echo, /bin/systemctl status tcp-echo, /opt/tcp_echo/scripts/*

ШАГ 2.3 · Каталог проекта

sudo mkdir -p /opt/tcp_echo
sudo chown alex:devops /opt/tcp_echo
sudo chmod 750 /opt/tcp_echo

sudo su - alex
cd /opt/tcp_echo

mkdir -p Server_Socket Client_Socket flask_app logs config scripts backups

chmod 755 Server_Socket Client_Socket   # приложение: все могут читать/входить
chmod 700 logs config                   # логи и конфиг: только владелец
chmod 750 scripts backups               # скрипты: владелец + группа

ls -la
# 1-й столбец = права, 3-й = владелец, 4-й = группа

ПОДСКАЗКА дальше работайте как пользователь alex.

ПРОВЕРКА

  • 4 пользователя: admin, alex, maria, john
  • alex ∈ devops; /opt/tcp_echo = 750, logs/ = 700


ЧАСТЬ 3 · TCP Echo Server

Скриншот №3 server + client терминалы

ТЕОРИЯ

Клиент  ──connect()──►  Сервер
        ◄──Echo: msg──   bind → listen → accept → thread

ШАГ 3.1 · server.py

nano Server_Socket/server.py
ФАЙЛ · Server_Socket/server.py
#!/usr/bin/env python3
"""
TechCorp TCP Echo Server.
Многопоточный сервер: каждый клиент  отдельный поток.
"""

import os
import socket
import threading

# PORT из переменной окружения (.env) или 5000 по умолчанию
PORT = int(os.environ.get("SERVER_PORT", 5000))
HOST = "0.0.0.0"  # слушать на всех интерфейсах (NAT + host-only)

clients = []
clients_lock = threading.Lock()  # защита списка clients от race condition


def handle_client(conn, addr):
    """Обработка одного TCP-клиента."""
    with clients_lock:
        clients.append(conn)
    print(f"[NEW] {addr} connected")

    try:
        while True:
            msg = conn.recv(1024).decode("utf-8")
            if not msg:
                break  # клиент закрыл соединение

            print(f"[{addr}] {msg}")

            # Команда graceful shutdown (для тестирования)
            if msg.lower().strip() == "baka":
                conn.send("Bye! See you soon.\n".encode())
                break

            conn.send(f"Echo: {msg}".encode())

    finally:
        with clients_lock:
            if conn in clients:
                clients.remove(conn)
        conn.close()
        print(f"[CLOSED] {addr}")


# --- Инициализация сервера ---
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # быстрый restart порта
server.bind((HOST, PORT))
server.listen(10)  # очередь до 10 pending-подключений
print(f"[STARTING] Server on {HOST}:{PORT}")

while True:
    conn, addr = server.accept()
    # daemon=True  поток завершится при остановке main
    threading.Thread(target=handle_client, args=(conn, addr), daemon=True).start()

ШАГ 3.2 · client.py

ФАЙЛ · Client_Socket/client.py
#!/usr/bin/env python3
"""TechCorp TCP Echo Client."""

import socket
import sys

# IP из аргумента или сервер по умолчанию
SERVER_IP = sys.argv[1] if len(sys.argv) > 1 else "192.168.56.10"
SERVER_PORT = 5000

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((SERVER_IP, SERVER_PORT))
print(f"[CONNECTED] to {SERVER_IP}:{SERVER_PORT}")

while True:
    msg = input("Send: ").strip()
    if not msg:
        continue

    client.send(msg.encode())
    reply = client.recv(1024).decode()
    print(f"Server: {reply}")

    if msg.lower() == "baka":
        break

client.close()
print("[CLOSED]")

ШАГ 3.3 · Тест

chmod +x Server_Socket/server.py Client_Socket/client.py

# Терминал 1  запуск сервера
python3 Server_Socket/server.py

# Терминал 2  клиент (с VM или Windows)
python3 Client_Socket/client.py 192.168.56.10

Ожидаемый результат:

Send: hello  →  Server: Echo: hello
Send: baka   →  Server: Bye! See you soon.

ПРОВЕРКА

  • Echo работает; baka закрывает сессию


ЧАСТЬ 4 · Мониторинг процессов и ресурсов

Скриншот №4 free -h + ss -tlnp | grep 5000

ТЕОРИЯ

Вопрос Команда
Сервис жив? ps, pgrep, ss
Хватает RAM? free -h
Хватает disk? df -h
Нагрузка CPU? uptime

ШАГ 4.1 · Диагностика

uptime                    # load average: 1/5/15 мин
free -h                   # total/used/available RAM
df -h /opt                # занятость диска (тревога если >80%)

ps aux | grep server.py   # процесс в списке всех процессов
pgrep -af server.py       # PID + полная командная строка

# -t TCP, -l LISTEN, -n numeric, -p process name
ss -tlnp | grep 5000

ПОДСКАЗКА ss заменяет устаревший netstat. Без -p используйте sudo.

ПРОВЕРКА

  • Процесс найден; порт 5000 в состоянии LISTEN


ЧАСТЬ 5 · Docker

Скриншот №5 docker ps + docker logs tcp-server

ТЕОРИЯ

Docker изолирует приложение с зависимостями.
--restart unless-stopped контейнер стартует после reboot сервера.

ШАГ 5.1 · Освободить порт 5000

pkill -f server.py
ss -tlnp | grep 5000    # вывод пуст  порт свободен

ШАГ 5.2 · Установка

sudo apt install docker.io -y
sudo usermod -aG docker alex    # alex может запускать docker без sudo
sudo systemctl enable docker
sudo systemctl start docker

# Перелогин обязателен для применения группы docker
exit && exit
ssh [email protected]
sudo su - alex

ШАГ 5.3 · Сборка и запуск

ФАЙЛ · Dockerfile
# Базовый образ с Python (минимальный размер)
FROM python:3.11-slim

WORKDIR /app

# Копируем только server.py  зависимостей нет (stdlib)
COPY Server_Socket/server.py .

ENV SERVER_PORT=5000
EXPOSE 5000

CMD ["python3", "server.py"]
cd /opt/tcp_echo

docker build -t tcp-echo .

docker run -d \
  --name tcp-server \
  --restart unless-stopped \
  -p 5000:5000 \
  tcp-echo

docker ps
docker logs tcp-server

# Тест: клиент подключается к localhost (контейнер на той же VM)
python3 Client_Socket/client.py 127.0.0.1

ПРОВЕРКА

  • STATUS Up; клиент подключается


ЧАСТЬ 6 · Nginx и Flask

Скриншот №6 nc 127.0.0.1 5001 + curl :8080/hello

ТЕОРИЯ

Клиент → Nginx :5001 → tcp-server :5000   (TCP stream)
Клиент → Nginx :8080 → flask-server :5002 (HTTP)

Backend не exposed наружу только через Nginx.

ШАГ 6.1 · Nginx TCP proxy

sudo apt install nginx netcat-openbsd -y
sudo systemctl enable nginx
sudo nano /etc/nginx/nginx.conf
ФАЙЛ · блок в /etc/nginx/nginx.conf (вне http)
# TCP proxy (L4)  проксирует сырой TCP-трафик
stream {
    upstream tcp_echo_backend {
        server 127.0.0.1:5000;    # Docker tcp-server
    }

    server {
        listen 5001;              # внешний порт для клиентов
        proxy_pass tcp_echo_backend;
        proxy_timeout 30s;
    }
}
sudo nginx -t                  # проверка синтаксиса  всегда перед reload!
sudo systemctl reload nginx

echo "test" | nc -w 3 127.0.0.1 5001
# Ожидаем: Echo: test

ШАГ 6.2 · Flask

ФАЙЛ · flask_app/app.py
#!/usr/bin/env python3
"""TechCorp Flask status app."""

from flask import Flask

app = Flask(__name__)


@app.route("/")
def home():
    return "<h1>TechCorp Flask App</h1>"


@app.route("/hello")
def hello():
    return "Hello from Flask!"


@app.route("/api/status")
def status():
    # JSON для мониторинга (curl / health-check)
    return '{"status":"running","service":"techcorp-flask"}'


if __name__ == "__main__":
    # 0.0.0.0  доступ из контейнера и через Nginx
    app.run(host="0.0.0.0", port=5000)
ФАЙЛ · flask_app/requirements.txt
flask==3.0.0
ФАЙЛ · Dockerfile.flask
FROM python:3.11-slim

WORKDIR /app
COPY flask_app/app.py flask_app/requirements.txt ./

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 5000
CMD ["python3", "app.py"]

ШАГ 6.3 · Nginx HTTP + запуск Flask

ФАЙЛ · /etc/nginx/conf.d/flask.conf
server {
    listen 8080;    # внешний HTTP-порт

    location / {
        proxy_pass http://127.0.0.1:5002;    # flask-server контейнер
        proxy_set_header Host $host;
    }
}
docker build -f Dockerfile.flask -t flask-app .
docker run -d \
  --name flask-server \
  --restart unless-stopped \
  -p 5002:5000 \
  flask-app

sudo nginx -t && sudo systemctl reload nginx

curl http://127.0.0.1:8080/hello
curl http://127.0.0.1:8080/api/status
docker ps

ПРОВЕРКА

  • nc :5001 → Echo; curl :8080 → Hello from Flask!


ЧАСТЬ 7 · Безопасность и автоматизация

Скриншот №7 ufw status verbose + ./scripts/status.sh

ТЕОРИЯ

Уровень Инструмент
Секреты .env с правами 600
Сеть UFW deny all, allow нужные порты
Операции bash-скрипт status.sh

ШАГ 7.1 · .env

cd /opt/tcp_echo
nano .env
ФАЙЛ · .env
# Конфигурация TCP Echo (не коммитить в git с секретами!)
SERVER_PORT=5000
LOG_LEVEL=INFO
ADMIN_EMAIL=[email protected]
chmod 600 .env       # только владелец читает/пишет
ls -la .env          # ожидаем: -rw-------

ШАГ 7.2 · status.sh

ФАЙЛ · scripts/status.sh
#!/bin/bash
# TechCorp  ежедневный health-check сервера

echo "========================================"
echo " Host: $(hostname)  |  $(date)"
echo "========================================"

echo ""
echo "=== Uptime & Load ==="
uptime

echo ""
echo "=== Memory ==="
free -h

echo ""
echo "=== Disk ==="
df -h /opt /var/log

echo ""
echo "=== Ports (22 SSH, 5000/5001 TCP, 8080 HTTP) ==="
ss -tlnp | grep -E '22|5000|5001|8080' || echo "No matching ports"

echo ""
echo "=== Docker containers ==="
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null \
  || echo "Docker not available"

echo ""
echo "=== systemd services ==="
for svc in ssh nginx docker; do
  printf "  %-10s %s\n" "$svc" "$(systemctl is-active $svc 2>/dev/null || echo unknown)"
done
chmod +x scripts/status.sh
./scripts/status.sh

ШАГ 7.3 · UFW Firewall

sudo apt install ufw -y

sudo ufw default deny incoming     # блокировать все входящие
sudo ufw default allow outgoing    # исходящие  разрешить

sudo ufw allow 22/tcp    comment 'SSH'
sudo ufw allow 5001/tcp  comment 'TCP Echo via Nginx'
sudo ufw allow 8080/tcp  comment 'Flask via Nginx'

sudo ufw enable
sudo ufw status verbose

Внимание: allow 22 до enable иначе потеряете SSH.

Дополнительно · systemd unit (альтернатива Docker для TCP)

Используйте либо Docker, либо systemd на порту 5000 не оба.

docker stop tcp-server
sudo nano /etc/systemd/system/tcp-echo.service
[Unit]
Description=TechCorp TCP Echo Server
After=network.target

[Service]
Type=simple
User=alex
WorkingDirectory=/opt/tcp_echo
EnvironmentFile=/opt/tcp_echo/.env
ExecStart=/usr/bin/python3 /opt/tcp_echo/Server_Socket/server.py
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now tcp-echo
sudo systemctl status tcp-echo

ПРОВЕРКА

  • .env = 600; status.sh OK; UFW allow 22/5001/8080


ЧАСТЬ 8 · Логи, cron и финальная проверка

Скриншот №8 crontab -l + финальная проверка

ТЕОРИЯ

Инструмент Назначение
docker logs Логи контейнера
journalctl Системный журнал systemd
cron Задачи по расписанию
backup.sh Резервное копирование конфигурации

ШАГ 8.1 · Логи

docker logs tcp-server --tail 20
docker logs flask-server --tail 10

# Логи nginx и ssh из systemd journal
sudo journalctl -u nginx --no-pager -n 15
sudo journalctl -u ssh --no-pager -n 10

ШАГ 8.2 · backup.sh

ФАЙЛ · scripts/backup.sh
#!/bin/bash
# TechCorp  резервная копия конфигурации и кода

BACKUP_DIR="/opt/tcp_echo/backups"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p "$BACKUP_DIR"

tar -czf "$BACKUP_DIR/backup_${DATE}.tar.gz" \
    -C /opt/tcp_echo \
    Server_Socket Client_Socket scripts .env config \
    2>/dev/null

# Удалить архивы старше 7 дней (ротация)
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete

echo "[OK] Backup created: backup_${DATE}.tar.gz"
ls -lh "$BACKUP_DIR" | tail -3
chmod +x scripts/backup.sh
./scripts/backup.sh

ШАГ 8.3 · Cron

crontab -e
ФАЙЛ · crontab пользователя alex
# Health-check каждые 15 минут
*/15 * * * * /opt/tcp_echo/scripts/status.sh >> /opt/tcp_echo/logs/health.log 2>&1

# Backup каждый день в 02:00
0 2 * * * /opt/tcp_echo/scripts/backup.sh >> /opt/tcp_echo/logs/backup.log 2>&1
crontab -l

ШАГ 8.4 · Финальная проверка

echo "========== FINAL CHECK =========="

./scripts/status.sh
ping -c 2 192.168.56.1
echo "ok" | nc -w 3 127.0.0.1 5001
curl -sf http://127.0.0.1:8080/hello
docker ps
sudo ufw status | head -10
crontab -l

echo "========== ALL DONE =========="

ПРОВЕРКА

  • Backup создан; cron 2 задачи; все команды OK


Итоговая таблица скриншотов

Тема Содержание
1 Сеть + SSH ip addr show enp0s8 · systemctl status ssh
2 Users + права groups alex · ls -la /opt/tcp_echo
3 TCP Echo server + client терминалы
4 Мониторинг free -h · ss -tlnp | grep 5000
5 Docker docker ps · docker logs tcp-server
6 Nginx + Flask nc 127.0.0.1 5001 · curl :8080/hello
7 UFW + status ufw status verbose · ./scripts/status.sh
8 Cron + финал crontab -l · FINAL CHECK

Сдача работы

# Артефакт
1 PDF-отчёт с 8 скриншотами
2 2–3 предложения к каждому скриншоту
3 Теория: модель клиент–сервер и роль systemd (5–7 предложений)
4 Одна проблема при выполнении и её решение

Устранение неполадок

Сеть и SSH
Симптом Решение
enp0s8 DOWN sudo ip link set enp0s8 up && sudo netplan apply
ping fail VirtualBox → Host Network Manager
SSH refused sudo systemctl start ssh
Порты и сервисы
Симптом Решение
Connection refused docker start tcp-server или python3 Server_Socket/server.py
Address in use pkill -f server.py или docker stop tcp-server
nginx error sudo nginx -t → исправить → sudo systemctl reload nginx
nc not found sudo apt install netcat-openbsd
Docker и UFW
Симптом Решение
permission denied sudo usermod -aG docker alex → перелогин
UFW locked out Консоль VM: sudo ufw allow 22

Справочник sysadmin

# === Утро: health-check ===
ssh [email protected]
/opt/tcp_echo/scripts/status.sh

# === Инцидент: диагностика ===
sudo journalctl -u nginx -n 30
docker logs tcp-server --tail 30
ss -tlnp | grep -E '5000|5001|8080'

# === Перезапуск сервисов ===
docker restart tcp-server flask-server
sudo systemctl restart nginx

Навыки для резюме

  • Ubuntu Server: Netplan, SSH, users, sudo, UFW
  • Мониторинг: ps, ss, free, df, journalctl, docker logs
  • Docker: build, run, restart policies
  • Nginx: stream (TCP) + HTTP reverse proxy
  • Автоматизация: bash, cron, backup
  • Python: TCP sockets, threading

Сетевые системы и приложения
М. Коротеев

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors