Durante um bom tempo, consumi tutoriais de homelab com a vontade de montar o meu. Canais de tech como Diolinux e TechHut vivem mostrando projetos incríveis, e a ideia de ter meu próprio ecossistema sempre me fascinou. O assunto furou tanto a bolha que virou uma verdadeira febre nos últimos anos.

Só que manter um servidor físico em casa, lidando com roteador bloqueado de provedor, sem IP fixo e equipamento ligado 24/7 fugia dos meus planos. Por mais que seja legal demais brincar com um Raspberry Pi ou reciclar um celular (já rodei o AdGuard Home num android antigo), eu queria uma parada limpa, sem puxar cabos e sem mais um equipamento piscando na minha mesa.

A alternativa foi buscar um laboratório “de verdade” na nuvem. O objetivo era ter um ambiente prático para estudar redes, Docker e deploy, mas sem precisar investir em hardware dedicado.

Então descobri que a Oracle Cloud tem um nível gratuito que é bom demais pra ser verdade: uma VM com até 24GB de RAM e 4 núcleos ARM ou 1GB de RAM e 1 núcleo x86 (que é a que estou usando), 200GB de disco e IP público fixo. Tudo 100% gratuito. Parece até post patrocinado, mas é apenas um serviço bom demais mesmo. Resolvi testar. Algumas horas depois, eu tinha um servidor pessoal completo rodando na nuvem, com HTTPS, domínio próprio e vários serviços organizados num painel bem maneiro que virou, de fato, a minha homepage.

Esse post documenta tudo o que fiz, do zero até o ambiente rodando em produção.


O que você vai ter no final

  • Um servidor Ubuntu na Oracle Cloud (grátis)
  • IP público fixo com domínio via DuckDNS
  • Docker gerenciando todos os serviços
  • Nginx Proxy Manager com SSL automático (HTTPS em tudo)

Os seguintes serviços rodando:

  • Homepage — painel central com links pra tudo - extremamente personalizável, a homepage perfeita e definitiva.
  • FileBrowser — interface web intuitiva para gerenciar arquivos diretamente no servidor.
  • Jellyfin — servidor de vídeo para cursos, filmes, séries e animes. Ele salva seu histórico e onde você parou; excelente para assistir suas aulas em qualquer lugar. Ele funciona como um Netflix pessoal, você assiste os vídeos direto do navegador! Apenas cuidado com o limite de 200GB e lembre-se de desabilitar o transcoding na VM.Standard.E2.1.Micro.
  • Navidrome — streaming de músicas (Spotify pessoal, sem anúncios, sem lag, com apps clients extremamente bons para android e iOS, uso Navisonic)
  • Memos — bloco de notas rápido Em vez de se expor ou se estressar no X, guarde seus pensamentos aqui e faça anotações. O app é incrível e permite criar contas para outras pessoas também.
  • Actual Budget — controle financeiro pessoal direto, simples e robusto. É um absurdo uma ferramenta dessas ser free.
  • Kavita — o melhor leitor de mangás, livros e PDFs que existe. Você terá seu próprio “Kindle” ou “Playbooks” que sincroniza em qualquer lugar.

Sinta-se livre para adicionar o serviço que quiser via docker. Esses foram selecionados ao meu gosto para atender minhas necessidades. Como verá a seguir, é bem simples e basta replicar os passos para o serviço desejado. Você pode ter o Adguard Home, PiHole, Wordpress, diversas coisas, só respeitar os limites do servidor.


Parte 1 - Criando a VM na Oracle Cloud

Criando a instância

Crie uma conta Always Free na Oracle Cloud, é bem simples e valide a conta com o seu cartão, nada será cobrado. Entre no painel da Oracle e vá em Compute > Instances > Create Instance.

Nas configurações:

  • Name: escolha qualquer nome (homelab-server, por exemplo)
  • Image: altere para Ubuntu 22.04 ou 24.04 (Usei 22.04)
  • Shape: aqui está a parte interessante. Você tem duas opções gratuitas:
    • VM.Standard.E2.1.Micro — AMD, 1GB RAM. Funciona, mas é limitada. (Tudo que eu fiz aqui foi nela.)
    • VM.Standard.A1.Flex — ARM, até 24GB RAM e 4 OCPUs. Essa é a escolha certa se você vai querer instalar muitos outros serviços. Muito potente, absurda.

Ambas têm a tag “Always Free”, mas a A1 pode não estar disponível em todas as regiões imediatamente. Se aparecer indisponível, tente criar novamente algumas horas depois, pois costuma liberar. No meu caso, não liberou de imediato, então montei toda essa estrutura na Standard E2.1.Micro mesmo e ela me atendeu super bem. A dica é: não fique bitolado com isso.

  • Networking: deixe no padrão. A Oracle cria a rede automaticamente.
  • SSH keys: clique em Save private key e guarde esse arquivo .key. Sem ele, você perde o acesso ao servidor para sempre. Você também pode gerar uma chave SSH e usar ela.
  • Boot Volume: marque Specify a custom boot volume size e coloque 200 GB. Esse é o limite gratuito — faça isso agora para não precisar expandir pelo terminal depois.

Clique em Create e aguarde o ícone ficar verde.

Fixando o IP público

Por padrão, a Oracle dá um IP “efêmero” que pode mudar se a VM reiniciar. Para usar domínios (DNS), você precisa de um IP fixo (até dá pra configurar um update automático, mas se temos o fixo pra quê se preocupar com isso, não é mesmo? Vamos aproveitar!).

  1. Vá em Networking > IP Management > Reserved Public IPs
  2. Clique em Reserve Public IP Address, dê um nome e reserve. Anote esse IP.
  3. Volte para a sua instância, role para baixo e clique em Attached VNICs
  4. Clique na VNIC principal > IPv4 Addresses
  5. Ao lado do IP atual, clique nos três pontos > Edit
  6. Selecione No public IP e salve (isso remove o IP temporário)
  7. Abra o edit novamente, selecione Reserved public IP, escolha o que você criou e salve

Pronto. Seu servidor agora tem um IP permanente.

Abrindo as portas no firewall da nuvem

A Oracle bloqueia tudo por padrão, exceto a porta 22 (SSH). Precisamos abrir as portas 80 e 443 para o tráfego web.

Vá novamente em Instances, clique na sua instância, em Instance details clique no link da sua Virtual Cloud Network (VCN), depois em Subnets e no link da sua Subnet pública, depois Security e no link da Default Security List.

Clique Security Rules e em Add Ingress Rules e configure:

Campo Valor
Source Type CIDR
Source CIDR 0.0.0.0/0
IP Protocol TCP
Destination Port Range 80,443,81,8080
Description Nginx Proxy Manager

Salve. Por questão de segurança, deixe apenas essas quatro portas abertas na nuvem — os serviços internos (Jellyfin, Navidrome etc.) serão roteados pelo Nginx e não precisam ficar expostos diretamente. Depois de toda a configuração e tudo roteado pelo Nginx, precisamos voltar aqui e excluir a porta 8080 e 81. Sem pontas soltas.

Detalhes dos Recursos Always Free: VM.Standard.A1.Flex ARM: Até 4 instâncias com um total de 4 OCPUs e 24 GB de RAM. VM.Standard.E2.1.Micro x86: 2 instâncias, cada uma com 1 OCPU e 1 GB de RAM. Armazenamento: Máximo total de 200 GB para volumes de blocos (total entre as VMs).


Parte 2 — Preparando o Ubuntu

Primeiro acesso via SSH

Abra o terminal (PowerShell no Windows funciona bem) na pasta onde você salvou o arquivo .key:

ssh -i sua-chave.key ubuntu@SEU_IP_FIXO

Na primeira vez vai perguntar se você confia no servidor. Digite yes e dê Enter. Você está dentro.

Atualizando o sistema

Regra de ouro antes de instalar qualquer coisa:

sudo apt update && sudo apt upgrade -y

Criando o Swap de Emergência

Como o servidor tem RAM limitada, criar uma memória virtual (Swap) no disco evita que o sistema encerre seus containers de surpresa. Se você conseguiu pegar a VM com 24GB de RAM você pode pular isso aqui.

Execute os comandos abaixo para criar 2GB de Swap, aplicar a segurança necessária, ativá-lo e garantir que ele inicie junto com o servidor:

# 1. Cria o arquivo de 2GB e tranca as permissões
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile

# 2. Formata e liga o Swap em tempo real
sudo mkswap /swapfile
sudo swapon /swapfile

# 3. Salva a configuração para ser permanente após reboots
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Dica: Digite free -h para confirmar se o seu Swap já está ativo.

Instalando o FileBrowser

O FileBrowser é uma interface web para gerenciar arquivos no servidor — você vai usá-lo para criar e editar os arquivos de configuração sem precisar ficar no terminal. Vamos instalá-lo como serviço do sistema para que suba automaticamente com o servidor.

# Instala o FileBrowser
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash

# Cria a pasta principal do homelab
mkdir ~/homelab

# Cria o serviço systemd
sudo bash -c 'cat <<EOF > /etc/systemd/system/filebrowser.service
[Unit]
Description=Filebrowser
After=network.target

[Service]
User=ubuntu
ExecStart=/usr/local/bin/filebrowser -r /home/ubuntu -a 0.0.0.0 -p 8080
Restart=always

[Install]
WantedBy=multi-user.target
EOF'

# Ativa e inicia
sudo systemctl daemon-reload
sudo systemctl enable filebrowser
sudo systemctl start filebrowser

O FileBrowser estará rodando em segundo plano na porta 8080.

Instalando o Docker

# Baixa e executa o instalador oficial
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Dá permissão ao usuário ubuntu para usar o Docker sem sudo
sudo usermod -aG docker ubuntu

Importante: para a permissão funcionar, saia do servidor (exit) e entre novamente via SSH.

Liberando portas no firewall interno

O painel da Oracle já está configurado, mas o Ubuntu tem seu próprio firewall (iptables) que também bloqueia portas. Abra as que vamos usar:

sudo iptables -I INPUT 1 -p tcp -m multiport --dports 80,443,81,3000,4533,5000,5006,5230,8080,8096 -j ACCEPT

# Salva a regra para persistir após reinicializações
sudo netfilter-persistent save

Aproveita e já testa o FileBrowser na URL http://SEU_IP_FIXO:8080!


Parte 3 — Domínio, Docker Compose e SSL

Configurando o domínio com DuckDNS

Acesse duckdns.org, faça login e crie um subdomínio (por exemplo: meuservidor.duckdns.org). Aponte esse domínio para o seu IP fixo da Oracle.

O DuckDNS suporta wildcard DNS nativamente, o que significa que qualquer prefixo (arquivos.meuservidor.duckdns.org, videos.meuservidor.duckdns.org) já aponta automaticamente para o mesmo IP, sem configuração adicional.

Criando as pastas de mídia

mkdir ~/musicas ~/videos ~/livros
sudo chown -R ubuntu:ubuntu ~/musicas ~/videos ~/livros
sudo chmod -R 755 ~/musicas ~/videos ~/livros

O arquivo docker-compose.yml

Acesse o FileBrowser pelo navegador em http://SEU_IP:8080, entre na pasta homelab e crie um arquivo chamado docker-compose.yml com o conteúdo abaixo:

version: '3.8'

services:
# Proxy reverso e gerador de SSL

  nginx-proxy:
    image: jc21/nginx-proxy-manager:latest
    container_name: nginx-proxy
    restart: unless-stopped
    ports:
      - "80:80"
      - "81:81"
      - "443:443"
    volumes:
      - ./npm-data:/data
      - ./npm-letsencrypt:/etc/letsencrypt

# Painel central (dashboard) - ATENÇÃO! VOCÊ PRECISA EDITAR AQUI!!!
# Altere o meuservidor.duckdns.org para o endereço real do seu servidor.
# Pode testar com o IP:3000 primeiro.

  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - ./homepage-config:/app/config
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /:/hostfs:ro
    environment:
      - HOMEPAGE_ALLOWED_HOSTS=meuservidor.duckdns.org,SEU_IP_FIXO,SEU_IP_FIXO:3000

  memos:
    image: ghcr.io/usememos/memos:latest
    container_name: memos
    restart: unless-stopped
    ports:
      - "5230:5230"
    volumes:
      - ./memos-data:/var/opt/memos

  navidrome:
    image: deluan/navidrome:latest
    container_name: navidrome
    restart: unless-stopped
    ports:
      - "4533:4533"
    environment:
      ND_LOGLEVEL: info
    volumes:
      - ./navidrome-data:/data
      - /home/ubuntu/musicas:/music:ro

  jellyfin:
    image: lscr.io/linuxserver/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Sao_Paulo
    ports:
      - "8096:8096"
    volumes:
      - ./jellyfin-config:/config
      - /home/ubuntu/videos:/data/videos:ro

  actual_server:
    image: actualbudget/actual-server:latest
    container_name: actual
    restart: unless-stopped
    ports:
      - "5006:5006"
    environment:
      - ACTUAL_PORT=5006
    volumes:
      - ./actual-data:/data

  kavita:
    image: jvmilazz0/kavita:latest
    container_name: kavita
    restart: unless-stopped
    environment:
      - TZ=America/Sao_Paulo
    ports:
      - "5000:5000"
    volumes:
      - ./kavita-data:/kavita/config
      - /home/ubuntu/livros:/kavita/data/livros

Lembre de substituir meuservidor.duckdns.org pelo seu domínio real no campo HOMEPAGE_ALLOWED_HOSTS.

Se você tiver algum problema para salvar esse arquivo com o FileBrowser, teste rodar o seguinte comando via SSH:

sudo chown -R ubuntu:ubuntu ~/homelab
chmod -R 755 ~/homelab

Subindo tudo

De volta ao terminal SSH:

cd ~/homelab
docker compose up -d

O Docker vai baixar todas as imagens e iniciar os containers em segundo plano. Na primeira vez pode demorar alguns minutos dependendo da velocidade de download.

Configurando o Nginx Proxy Manager (SSL)

Acesse o painel do NPM em http://SEU_IP:81.

Login padrão: admin@example.com / changemetroque a senha imediatamente após o primeiro acesso.

Vá em Hosts > Proxy Hosts > Add Proxy Host e crie uma entrada para cada serviço. Em todos eles, vá na aba SSL, selecione “Request a new SSL Certificate” e ative Force SSL.

Conceito importante antes de configurar

Serviços que rodam dentro do Docker (Jellyfin, Memos, Navidrome etc.) devem usar o nome do container como Forward Hostname, pois estão na mesma rede virtual do Nginx.

O FileBrowser é uma exceção — ele foi instalado diretamente no Ubuntu (fora do Docker), então o Nginx precisa usar o IP privado do servidor para encontrá-lo. Atenção: é o privado, não o público aqui. Como vamos bloquear a porta 8080, o Nginx vai usar o próprio IP da máquina para encontrar o FileBrowser e fazer o roteamento. O ip privado na Oracle geralmente se parece com 10.0.0.X. Esse IP não muda nunca enquanto a VM existir.

Tabela de configuração dos hosts

Serviço Domain Names Forward Hostname Forward Port
Homepage meuservidor.duckdns.org homepage 3000
FileBrowser arquivos.meuservidor.duckdns.org SEU_IP_PRIVADO 8080
Jellyfin videos.meuservidor.duckdns.org jellyfin 8096
Navidrome musicas.meuservidor.duckdns.org navidrome 4533
Memos notas.meuservidor.duckdns.org memos 5230
Actual Budget financas.meuservidor.duckdns.org actual 5006
Kavita livros.meuservidor.duckdns.org kavita 5000

Você deve inserir essas informações dentro de Details em Edit Proxy Host. O Domain Name para cada serviço, o Scheme é http para todos, o forward Hostname conforme na tabela e a Forward Port. Em options ainda em Details marque as 3 caixinhas de Cache Assets, Block Common Exploits e Websockets Support.

Depois de salvar cada host, o NPM vai requisitar o certificado SSL automaticamente via Let’s Encrypt. Em poucos segundos cada serviço estará acessível via HTTPS.


Parte 4 — Finalizando com o painel Homepage e Segurança

Acesse o FileBrowser (agora em https://arquivos.meuservidor.duckdns.org), navegue até homelab/homepage-config e edite o arquivo services.yaml:

- Meu Servidor:
    - Arquivos:
        icon: filebrowser.png
        href: https://arquivos.meuservidor.duckdns.org
        description: Gerenciador de Arquivos
    - Videos:
        icon: jellyfin.png
        href: https://videos.meuservidor.duckdns.org
        description: Plataforma de Vídeos
    - Biblioteca:
        icon: kavita.png
        href: https://livros.meuservidor.duckdns.org
        description: Mangás, Livros e PDFs
    - Músicas:
        icon: navidrome.png
        href: https://musicas.meuservidor.duckdns.org
        description: Servidor de Músicas
    - Finanças:
        icon: actualbudget.png
        href: https://financas.meuservidor.duckdns.org
        description: Controle Orçamentário
    - Anotações:
        icon: memos.png
        href: https://notas.meuservidor.duckdns.org
        description: Notas Rápidas

Agora o arquivo settings.yaml:

title: "Meu Server"
theme: dark
color: zinc

# Configuração do Papel de Parede
background:
  image: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=2564&auto=format&fit=crop" # Link para qualquer papel de parede
  blur: "sm" # Desfoque leve
  brightness: "50" # Escurece a imagem para destacar os botões

# Força os links a ficarem em linha (lado a lado)
layout:
  Meu Servidor:
    style: row
    columns: 3

# Limpeza visual
hideVersion: true

E pra dar um estilozinho bacana para sua página Home, vamos colocar uns widgets para monitorar cpu, memória e disco no arquivo widgets.yaml:

- resources:
    cpu: true
    memory: true
    disk: /hostfs

- search:
    provider: duckduckgo
    target: _blank

Salve e atualize a página principal do seu domínio. Tudo organizado, tudo com HTTPS, tudo de graça.

Fechando Portas

Volte para as Ingress Rules (Se não lembra como, verifique novamente essa sessão) e delete as portas extras que abrimos, mantenha apenas a 22, os serviços de ICMP, a 80 e a 443.

Túnel SSH

O painel do Nginx Proxy Manager agora não será mais acessível por ninguém. Se você precisar acessar ele, você pode acessar com um túnel via SSH. É a opção mais recomendada para não deixar o painel aberto para a web.

ssh -i sua-chave.key -L 8081:localhost:81 ubuntu@SEU_IP_FIXO

Note que é quase o mesmo comando para acessar o servidor via SSH, apenas com o comando -L 8081:localhost:81 no meio, que é a criação do túnel. Com essa janela aberta, você consegue acessar o Nginx Proxy Manager direto no seu PC pela URL localhost:8081. Quando fechar a janela, o túnel se fecha.


Considerações finais

O que mais me surpreendeu nesse projeto foi a relação custo-benefício da Oracle Cloud Free Tier. A VM A1 com ARM é absurda de poderosa para uso pessoal, roda todos esses serviços simultâneos easy e você pode facilmente adicionar outros incríveis que existem, só adicionar mais algumas linhas no arquivo do docker, subir no Nginx e atualizar a homepage!

A VM.Standard.E2.1.Micro que é a que eu estou usando também não ficou pra trás! Parece muito pouco (1 núcleo e 1 GB de RAM), mas como não executamos nenhuma GUI e o Ubuntu 22.04 é bem leve, ela entrega tudo. Chego perto do limite, mas nunca tive problema nenhum. Na real, ainda sobram 300 MB de RAM, às vezes mais! Só uma dica importante: se for usar o Jellyfin nessa máquina, desative a transcodificação. E não deixe de criar o swap.

Alguns pontos e coisas que aprendi no processo:

  • Segurança: Deixe apenas as portas 80 e 443 abertas no firewall da Oracle. Nunca exponha diretamente as portas dos serviços (8096, 4533 etc.) — o Nginx cuida disso.
  • Backups: Os dados dos containers ficam nas subpastas dentro de ~/homelab (npm-data, jellyfin-config, navidrome-data etc.). Para fazer backup, basta comprimir essa pasta inteira e guardar em algum lugar seguro. O docker compose up -d recria tudo a partir dessas pastas.
  • Escalabilidade: A arquitetura com Docker Compose é modular. Quer adicionar um novo serviço? Basta incluir um novo bloco no docker-compose.yml, rodar docker compose up -d novamente e criar mais uma entrada no Nginx. Sem reinstalações, sem conflitos.
  • Filebrowser: Deixei o Filebrowser fora do Docker Compose de propósito durante a instalação. Queria testar e ajustar tudo na mão enquanto configurava. Mas ele pode ser facilmente adicionado via Docker também — é só incluir o bloco no docker-compose.yml que roda tranquilamente.

No fim, saí de “queria montar um homelab” para um servidor real, com domínio, SSL e sete serviços rodando, sem gastar nada. Valeu cada minuto!


Tem dúvida ou sugestão? Me manda uma mensagem.