Jak skonfigurować hosting S3 na własnym serwerze

Wstęp

W tym przewodniku pokażę, jak w prosty i tani sposób utworzyć hosting S3 na własnym serwerze. 🖥️
Wykorzystamy aplikację MinIO na VPS-ie. Możesz wybrać dowolnego dostawcę, który odpowiada Twoim potrzebom (np. Hetzner, AWS, Azure lub OVH).
Ja osobiście używam taniego VPS-a z Ubuntu 1 GB RAM od mikr.us. Z dodatkowym dyskiem twardym mój całkowity koszt wynosi 110 PLN rocznie (około 26,5 USD).

[Bonus 2025-06]: Integracja z CrowdSec do wykrywania ataków i podejrzanego ruchu na stronie

VPS Hardening

Przed rozpoczęciem konfiguracji polecam przeprowadzenie wstępnej konfiguracji nowego serwera VPS. Obejmuje to ustawienie dwóch rekordów A w strefie DNS (np. s3.contoso.com i *.s3.contoso.com), konfigurację hasła root, utworzenie nowego użytkownika oraz wyłączenie logowania przez SSH na hasło. Proces ten, znany jako VPS Hardening 🪪, znacznie zwiększa bezpieczeństwo serwera. W sieci znajdziesz wiele zasobów na ten temat, więc zachęcam do poszukania informacji.

Zaczynajmy! 🔥

Utworzenie użytkownika i grupy dla MinIO

Dla bezpieczeństwa i izolacji usług stworzymy dedykowanego użytkownika i grupę dla MinIO. Dzięki temu aplikacja nie będzie działać na koncie root. 🛂

Wykonaj następujące komendy na serwerze Ubuntu:

sudo groupadd minio
sudo useradd -r -g minio -s /usr/sbin/nologin minio

Ten użytkownik będzie później odpowiedzialny za uruchamianie usługi MinIO, co zapewni minimalne uprawnienia zgodnie z najlepszymi praktykami bezpieczeństwa.

Tworzenie katalogu do przechowywania danych MinIO i nadawanie uprawnień

Następnie musimy utworzyć dedykowany katalog na dane MinIO i przypisać odpowiednie uprawnienia, aby użytkownik MinIO miał pełną kontrolę nad tym katalogiem. 📂

Uruchom poniższe polecenia na serwerze Ubuntu:

sudo mkdir -p /storage/minio
sudo chown minio:minio /storage/minio
sudo chmod 750 /storage/minio

Konfiguracja MinIO i pobieranie binariów MinIO

Po utworzeniu katalogu do przechowywania danych, kolejnym krokiem jest utworzenie folderu danych w jego wnętrzu oraz pobranie binariów MinIO. To przygotuje środowisko do uruchomienia usługi MinIO. ☁️

Wykonaj następujące polecenia, aby kontynuować:

sudo mkdir -p /storage/minio/data
cd /storage/minio
sudo wget https://dl.min.io/server/minio/release/linux-amd64/minio
sudo chown -R minio:minio /storage/minio
sudo chmod 750 /storage/minio
sudo chmod +x /storage/minio/minio
sudo chown -R minio:minio /storage/minio/data
sudo chmod u+rxw /storage/minio/data

Tworzenie i konfigurowanie usługi systemd dla MinIO

Aby MinIO uruchamiało się automatycznie i działało jako zarządzana usługa, stworzymy nową usługę systemd. Usługa ta uruchomi MinIO z niezbędnymi zmiennymi środowiskowymi dla API, CLI i konsoli internetowej. 🛠️

Krok 1: Tworzenie pliku usługi systemd

Najpierw uruchom polecenie: sudo nano /etc/systemd/system/minio.service
i dodaj następującą konfigurację do pliku: (podmień hasło i domenę!)

[Unit]
Description=MinIO Object Storage
After=network.target

[Service]
User=minio
Group=minio
ExecStart=/storage/minio/minio server /storage/minio/data \
--address :9000 \
--console-address :40288
Environment="MINIO_ROOT_USER=admin"
Environment="MINIO_ROOT_PASSWORD=strongpassword123"
Environment="MINIO_DOMAIN=<DOMAIN>"
Restart=always
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

ExecStart – Uruchamia MinIO z określoną ścieżką do przechowywania danych i wiąże API/CLI z portem 9000, a konsolę internetową z portem 40288. W moim przypadku używam portów TCP skonfigurowanych w panelu mikr.us.
Environment – Definiuje użytkownika root i hasło dla MinIO. Zastąp admin oraz strongpassword123 bezpiecznymi danymi logowania. Nie zapomnij o domenie!
Restart=always – Zapewnia ponowne uruchomienie MinIO w przypadku awarii lub restartu serwera.

Krok 2: Włączanie i uruchamianie usługi MinIO ▶️

Zapisz i zamknij plik, a następnie przeładuj demona systemd, aby zastosować zmiany:

sudo systemctl daemon-reload
sudo systemctl enable minio
sudo systemctl start minio


Krok 3: Weryfikacja statusu usługi i logów 🔍

Aby upewnić się, że MinIO działa poprawnie, sprawdź jego status i przejrzyj logi:

sudo systemctl status minio
sudo journalctl -u minio

W tym momencie MinIO powinno być dostępne przez API pod adresem http://<adres-IP-serwera>:9000 oraz przez konsolę internetową pod adresem http://<adres-IP-serwera>:44935.

Tworzenie bucketu i klucza dostępu

Ostatnim krokiem jest stworzenie bucketu i wygenerowanie klucza dostępu. Przejdź do panelu “Buckets” i kliknij “Create Bucket”. Nazwę swój bucket tutorial-bucket. 🪣

[2025-06-24] Uwaga!
Niestety zespół MinIO w jednej z ostatnich aktualizacji postanowił… usunąć prawie wszystkie funkcjonalności panelu Web UI, aby zmotywować ludzi do przejścia na płatną wersję za … uwaga $100k rocznie.

Kolejne etapy poradnika, które odbywają sięna Web UI, będziesz musiał wykonać poprzez CLI. W tym celu pobierz na swoim lokalnym komputerze (nie na serwerze VPS!) program mc:
MinIO Admin Client — MinIO Object Storage for Linux

Następnie zaloguj się do serwera MinIO za pomocą
.\mc.exe alias set minio https://<DOMAIN>:9000 admin 'strongpassword123'

Finalnie będziesz sprawdź połączenie komendą:
.\mc.exe admin info minio

Dodawanie/usuwanie bucketów, access-key będziesz musiał zrobić poprzez CLI (program mc) z pomocą dokumentacji -> mc admin config — MinIO Object Storage for Linux

Teraz utwórz nowy klucz dostępu. Otwórz panel „Access Keys” i kliknij “Create Access Key”. Nazwę go tutorial-bucket-rw, wskazując, że klucz ma prawa odczytu i zapisu dla bucketu tutorial-bucket. 🔑

Pamiętaj, aby zapisać sekret w bezpiecznym miejscu, ponieważ nie będzie można go później wyświetlić.

Ostatecznym krokiem konfiguracji jest przypisanie odpowiednich uprawnień do naszego klucza dostępu. 🛂

Kliknij ikonę ołówka obok nowego klucza i wklej następujący tekst w polu “Access Key Policy”:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::tutorial-bucket/*"
]
}
]
}

Dzięki temu klucz otrzyma uprawnienia do listowania, odczytu, zapisu i usuwania obiektów w ramach tutorial-bucket, co zapewni pełny dostęp do zarządzania zawartością.

Na potrzeby testów skonfigurowałem jedną z wtyczek WordPressa, aby przesyłała kopie zapasowe do naszego nowego bucketu S3. Jak widać, wprowadziłem dane logowania oraz wyłączyłem weryfikację SSL w ustawieniach wtyczki.

Wszystko działa poprawnie. ✅

Konfiguracja SSL dla MinIO za pomocą Certbota i automatycznej synchronizacji certyfikatów

Aby zapewnić podstawowe standardy bezpieczeństwa, musimy skonfigurować SSL dla naszej instancji MinIO 🛜. Osiągniemy to za pomocą Certbota oraz stworzenia usługi, która automatycznie synchronizuje certyfikaty do odpowiedniego katalogu.

Krok 1: Konfiguracja Certbota

Najpierw skonfiguruj Certbota. Nie będę powielać dostępnych informacji, więc po prostu postępuj zgodnie z poniższym przewodnikiem:
🔗 How to Acquire a Let’s Encrypt Certificate Using DNS Validation with ACME-DNS and Certbot on Ubuntu 18.04

Po uruchomieniu polecenia:

sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d <YOUR_DOMAIN> -d *.<YOUR_DOMAIN>

Certyfikaty privkey.pem i cert.pem zostaną wygenerowane w katalogu: /etc/letsencrypt/live/<YOUR_DOMAIN>/

Krok 2: Tworzenie usługi 🛠️

Gdy to zrobisz, możemy przystąpić do tworzenia naszej usługi. Utwórz nowy katalog za pomocą następujących poleceń:

sudo mkdir -p /home/minio/.minio/certs
sudo chown -R minio:minio /home/minio
sudo chmod u+rxw -R /home/minio

Następnie stwórz plik skryptu w sudo nano /usr/local/bin/minio_sync_certs.sh z następującą zawartością (pamiętaj, aby zastąpić `<YOUR_DOMAIN>`):

#!/bin/bash

CERT_SRC="/etc/letsencrypt/live/<YOUR_DOMAIN>/fullchain.pem"
KEY_SRC="/etc/letsencrypt/live/<YOUR_DOMAIN>/privkey.pem"

CERT_DST="/home/minio/.minio/certs/public.crt"
KEY_DST="/home/minio/.minio/certs/private.key"

cp "$CERT_SRC" "$CERT_DST"
cp "$KEY_SRC" "$KEY_DST"

chmod 600 "$KEY_DST"
chmod 644 "$CERT_DST"
chown -R minio:minio "$KEY_DST"
chown -R minio:minio "$CERT_DST"

Teraz nadaj uprawnienia do wykonywania skryptu poleceniem sudo chmod +x /usr/local/bin/minio_sync_certs.sh

Po tym stwórz plik usługi w sudo nano /etc/systemd/system/minio-sync-certs.service z następującą zawartością:

[Unit]
Description=Sync Lets Encrypt certificate to MinIO directory
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/minio_sync_certs.sh

[Install]
WantedBy=multi-user.target

Krok 3: Tworzenie timera usługi ⌚

Następnie skonfiguruj timer, który zautomatyzuje synchronizację certyfikatów. Utwórz plik za pomocą polecenia: sudo nano /etc/systemd/system/minio-sync-certs.timer i wprowadź następującą zawartość:

[Unit]
Description=Timer to synchronize Let's Encrypt certificates

[Timer]
OnBootSec=1min
OnUnitActiveSec=12h
Persistent=true

[Install]
WantedBy=timers.target

Na koniec włącz i uruchom timer:

sudo systemctl daemon-reload
sudo systemctl enable minio-sync-certs.timer
sudo systemctl start minio-sync-certs.timer

Teraz, gdy wykonamy polecenie: systemctl restart minio, powinniśmy zauważyć, że czerwona kłódka w przeglądarce zniknęła, co oznacza, że nasze połączenie jest teraz bezpieczne i szyfrowane za pomocą TLS. 🎉🚀

Podsumowanie

Gratulacje! Udało Ci się skonfigurować bezpieczne i ekonomiczne rozwiązanie do przechowywania danych kompatybilne z S3 za pomocą MinIO. Od konfiguracji VPS po włączenie szyfrowania SSL. Dzięki gotowej instancji MinIO możesz teraz bez obaw korzystać z niej do kopii zapasowych, przechowywania multimediów lub innych potrzeb związanych z chmurą. Powodzenia w hostingu! 🔥

[Bonus 2025-06] Zwiększenie bezpieczeństwa z integracją CrowdSec

Choć nasza konfiguracja MinIO jest funkcjonalna i zabezpieczona certyfikatami SSL, możemy znacząco poprawić jej poziom bezpieczeństwa poprzez implementację CrowdSec – kolaboracyjnego silnika bezpieczeństwa, który zapewnia ochronę w czasie rzeczywistym przed złośliwymi działaniami. 🛡️

CrowdSec działa jak nowoczesny system wykrywania i zapobiegania włamaniom, który analizuje wzorce logów w celu identyfikacji podejrzanych zachowań i automatycznie blokuje złośliwych użytkowników. W przeciwieństwie do tradycyjnych rozwiązań, CrowdSec wykorzystuje zbiorową inteligencję społeczności, dzieląc się danymi o zagrożeniach w celu ochrony wszystkich użytkowników przed nowymi atakami. Czyni to szczególnie wartościowym dla ochrony usług cloud storage takich jak nasza instancja MinIO, które są częstymi celami prób nieautoryzowanego dostępu, ataków brute force i prób eksfiltracji danych.

Aby zintegrować CrowdSec z naszą konfiguracją MinIO, musimy wprowadzić kilka zmian architektonicznych, które stworzą bardziej odporną i bezpieczną infrastrukturę:

  1. Rekonfiguracja portów: Modyfikacja MinIO do działania na porcie wewnętrznym (9001) zamiast publicznego (9000)
  2. Konfiguracja reverse proxy: Instalacja i konfiguracja Nginx jako reverse proxy do obsługi połączeń zewnętrznych
  3. Migracja certyfikatów SSL: Przeniesienie obsługi certyfikatów SSL z MinIO do Nginx dla lepszego zarządzania bezpieczeństwem
  4. Oczyszczanie usług: Wyłączenie automatycznej synchronizacji certyfikatów, która nie będzie już potrzebna
  5. Instalacja CrowdSec: Wdrożenie CrowdSec z kolekcją Nginx i firewall bouncer dla kompleksowej ochrony

Wprowadźmy te zmiany krok po kroku.

Krok 1: Rekonfiguracja portu MinIO

Najpierw musimy zmodyfikować naszą usługę MinIO, aby działała na porcie wewnętrznym. Edytuj plik usługi systemd:

sudo nano /etc/systemd/system/minio.service

Zmień parametr --address z :9000 na :9001 w linii ExecStart:

ExecStart=/storage/minio/minio server /storage/minio/data \
--address :9001 \
--console-address :40288

Następnie uruchom ponownie usługę MinIO:

sudo systemctl daemon-reload
sudo systemctl restart minio

Krok 2: Instalacja i konfiguracja Nginx

Zainstaluj Nginx, który będzie działał jako nasz reverse proxy:

sudo apt update
sudo apt install nginx -y

Utwórz nowy plik konfiguracyjny Nginx dla MinIO:

sudo nano /etc/nginx/sites-available/minio

Dodaj następującą konfigurację (zastąp <DOMAIN> swoją rzeczywistą domeną):

server {
listen 9000 ssl;
server_name <DOMAIN> *.<DOMAIN>;

ssl_certificate /etc/letsencrypt/live/<DOMAIN>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<DOMAIN>/privkey.pem;

# Ulepszona konfiguracja SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;

# Logowanie dla analizy CrowdSec
access_log /var/log/nginx/minio-access.log;
error_log /var/log/nginx/minio-error.log;

# MinIO wymaga specjalnej obsługi dla dużych plików
client_max_body_size 1000M;
proxy_request_buffering off;

location / {
proxy_pass http://127.0.0.1:9001;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_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 https;
proxy_set_header X-Forwarded-Port 9000;

proxy_buffering off;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;

}
}

Ważna uwaga dla użytkowników Cloudflare.
Jeśli używasz Cloudflare i zaznaczyłeś „Proxy” przy swoich rekordach DNS, to sytuacja się trochę komplikuje. Nasz serwer zamiast IP użytkownika będzie dostawać IP z CloudFlare i przykładowo analizowanie ruchu poprzez CrowdSec lub blokowanie ruchu przez bouncery (np. nftables) może nie działać poprawnie. Zatem jeśli używasz Cloudflare z proxy, to sugeruje dodać poniższy fragment, oraz zamiast bouncera nftables używać bouncera cloudflare

(...)
# Retreiving real IP from Cloudflare (ipv4)
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;

# Retreiving real IP from Cloudflare (ipv6)
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;

# Retreiving real IP from Cloudflare
real_ip_header CF-Connecting-IP;
real_ip_recursive on;

location / {
(...)

Włącz witrynę i przetestuj konfigurację:

sudo ln -s /etc/nginx/sites-available/minio /etc/nginx/sites-enabled/minio
sudo nginx -t
sudo systemctl enable nginx
sudo systemctl start nginx

Krok 3: Oczyszczanie synchronizacji certyfikatów

Ponieważ Nginx teraz bezpośrednio obsługuje certyfikaty SSL, możemy wyłączyć i usunąć usługę synchronizacji certyfikatów MinIO:

sudo systemctl disable minio-sync-certs.timer
sudo systemctl stop minio-sync-certs.timer
sudo systemctl disable minio-sync-certs.service

Usuń katalog certyfikatów MinIO:

sudo rm -rf /home/minio/.minio/certs
sudo systemctl restart minio

Krok 4: Instalacja i konfiguracja CrowdSec

Zainstaluj CrowdSec używając oficjalnego skryptu instalacyjnego:

curl -s https://install.crowdsec.net | sudo bash
sudo apt install crowdsec -y

Rejestracja w CrowdSec Console (opcjonalne, ale zalecane)

Aby skorzystać ze zbiorowej inteligencji i mieć dostęp do zaawansowanych funkcji, zarejestruj swoją instancję:

sudo cscli console enroll -e context <TWOJ_KLUCZ_REJESTRACJI>

Możesz uzyskać swój klucz rejestracji z CrowdSec Console.

Instalacja kolekcji Nginx

Zainstaluj kolekcję Nginx, aby umożliwić CrowdSec zrozumienie i analizę logów Nginx:

sudo cscli collections install crowdsecurity/nginx

Konfiguracja źródeł logów

Edytuj konfigurację akwizycji CrowdSec, aby monitorować nasze logi Nginx:

sudo nano /etc/crowdsec/acquis.yaml

Upewnij się, że następująca konfiguracja jest obecna:

filenames:
- /var/log/nginx/minio-access.log
- /var/log/nginx/minio-error.log
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginx

Instalacja Firewall Bouncer

Zainstaluj bouncer nftables, aby automatycznie blokować wykryte złośliwe IP:

sudo apt install crowdsec-firewall-bouncer-nftables -y

Restart usług

Uruchom ponownie CrowdSec, aby zastosować wszystkie konfiguracje:

sudo systemctl restart crowdsec
sudo systemctl restart crowdsec-firewall-bouncer

Krok 5: Dodatkowe wzmocnienie bezpieczeństwa

Lista zaufanych IP

Dodaj IP swojego serwera i inne zaufane serwery do allowlisty CrowdSec:

sudo cscli decisions add --ip <TWOJE_ZAUFANE_IP> --duration 0 --type ban --reason "Zaufany serwer"

Opcjonalnie: Wyłączenie konsoli web MinIO

Ponieważ konsola web MinIO ma ograniczoną funkcjonalność w najnowszych wersjach, możesz zdecydować się na jej całkowite wyłączenie. Edytuj plik usługi systemd:

sudo nano /etc/systemd/system/minio.service

Usuń parametr --console-address, zostawiając tylko:

ExecStart=/storage/minio/minio server /storage/minio/data \
--address :9001

Następnie uruchom ponownie usługę:

sudo systemctl daemon-reload
sudo systemctl restart minio

Monitorowanie i weryfikacja

Aby sprawdzić, czy CrowdSec działa poprawnie, możesz:

  1. Sprawdzić status CrowdSec:
sudo cscli metrics
  1. Wyświetlić aktywne decyzje (zablokowane IP):
sudo cscli decisions list
  1. Otworzyć MinIO na innym urządzeniu (np. na smartfonie) i spróbować go zbanować
# Check device traffic (IP address)
tail -f /var/log/nginx/minio-access.log

# Ban
cscli decisions add --ip 1.23.45.67 -d 5m

Zajrzyj też do tego artykułu Zabezpieczanie Coolify z CrowdSec: Kompletny przewodnik | hasto, aby zobaczyć jak możesz dodać powiadomienia Discord

Twoja instancja MinIO jest teraz chroniona przez inteligentne wykrywanie zagrożeń CrowdSec i automatyczne blokowanie. System będzie stale monitorować wzorce dostępu i blokować podejrzane działania, znacząco zwiększając bezpieczeństwo Twojego rozwiązania storage kompatybilnego z S3. 🚀

1 komentarz do “Jak skonfigurować hosting S3 na własnym serwerze”

  1. Odnośnik zwrotny: Właściwy sposób instalacji WordPressa i MySQL na Coolify | hasto

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Przewijanie do góry