Ada banyak cara untuk mengekspose HTTP service yang berada dibalik NAT supaya dapat diakses dari internet. Pada umumnya, teknik yang dilakukan adalah melakukan network tunnel menggunakan VPN dan HTTP reverse proxy. Cloudflare Tunnel adalah salah satu contoh yang menggunakan teknik ini.
Di artikel ini saya ingin berbagi pengalaman dan cara saya mengekspose HTTP service yang berada di jaringan lokal ke internet menggunakan WireGuard VPN tunnel dan Nginx sebagai HTTP reverse proxy. HTTP service yang akan saya expose adalah Immich. Bagi yang belum tahu, Immich adalah solusi manajemen foto dan video yang dapat dihosting sendiri; sebuah alternatif dari Google Photos.
Saya tidak akan membahas detail cara menginstall Immich karena proses instalasi Immich menggunakan Docker sangat mudah dilakukan. Saya akan lebih fokus ke konfigurasi Nginx dan VPN tunnel, serta topologi yang digunakan.
Prasyarat
Sebelum memulai ada beberapa kondisi yang perlu dipenuhi, yaitu:
- Sebuah nama domain atau subdomain yang menggunakan Cloudflare sebagai authoritative DNS server.
- Sebuah VPS dengan IP public (sudah terinstall WireGuard dan Nginx yang nantinya digunakan untuk reverse proxy ke jaringan lokal).
- Sebuah PC / VM / LXC di jaringan lokal untuk menjalankan Nginx, Docker dan Certbot.
Topologi
Sebelum memulai, saya ingin membagikan topologi jaringan yang saya gunakan saat artikel ini dibuat.
Ijinkan saya menjelaskan topologi diatas dan memberikan tambahan informasi untuk mengikuti artikel ini:
- Subdomain yang saya gunakan untuk Immich adalah
i.arch.or.id
. - IP publik VPS server yang saya gunakan adalah
154.26.xxx.xx
. - IP VPS server untuk WireGuard tunnel adalah
10.88.88.51
. - Jaringan LAN menggunakan segmen
192.168.2.0/24
. - Immich terinstall di LXC yang berada di jaringan lokal dengan alamat IP
192.168.2.105
. - LXC Immich terkoneksi ke VPS server dan menggunakan IP tunnel
10.88.88.105
. - Di LXC Immich juga terinstall Nginx dan Certbot.
Tujuan akhir dari artikel ini adalah aplikasi Immich dapat diakses dari internet dan seluruh perangkat yang berada pada jaringan lokal dapat terkoneksi secara langsung ke server Immich tanpa harus memutar ke internet.
Jadi ketika saya berada di luar rumah, saya masih tetap bisa mengakses foto dan video saya yang berada di rumah melalui aplikasi Immich. Sedangkan saat saya berada dirumah, saya dapat secara leluasa melakukan sinkronisasi atau upload foto dan video lebih cepat karena terkoneksi langsung menggunakan jaringan LAN.
Konfigurasi
Cloudflare: DNS record & Edge Certificates
Anda perlu mendelegasikan authoritative DNS server ke Cloudflare kemudian
tambahkan atau arahkan A
/AAAA
record untuk subdomain yang akan digunakan
oleh immich ke IP public VPS Anda. Di artikel ini berarti saya mengarahkan A
record i.arch.or.id
ke IP 154.26.xxx.xx
.
Ada beberapa setting default dari Cloudflare yang perlu dirubah supaya LXC dapat melakukan request sertifikat SSL menggunakan certbot, yaitu:
- Mengubah mode enkripsi ke
Full
. Caranya masuk ke manajemen domain -> SSL/TLS -> Overview. Pada bagian “SSL/TLS encryption” ubah encryption mode keFull
. Hal ini perlu dilakukan supaya Cloudflare mau menerima “self-signed certificate” dari origin server. - Mendisable “Always Use HTTPS” dan “Automatic HTTPS Rewrites”. Caranya masuk ke manajemen domain -> Edge Certificates. Pastikan “Always Use HTTPS” dan “Automatic HTTPS Rewrites” tidak aktif. Hal ini perlu dilakukan supaya verifikasi SSL request dari LXC ke Let’s Encrypt server berjalan dengan lancar.
VPS: WireGuard & Nginx
Anda perlu mensetting dan menjalankan WireGuard di VPS server yang nantinya digunakan untuk berkomunikasi dengan LXC server yang berada di jaringan lokal. Jika Anda belum pernah melakukan konfigurasi WireGuard, Anda dapat membaca artikel saya sebelumnya tentang cara setup WireGuard VPN server secara manual atau menggunakan WireGuard-UI.
Kurang lebih, konfigurasi WireGuard di VPS server saya sebagai berikut:
1[Interface]
2PrivateKey = SomeRandomStringThatShouldBePrivate
3Address = 10.88.88.51/22
4ListenPort = 51822
5
6# Immich LXC server
7[Peer]
8PublicKey = SomeRandomStringThatPublicMayKnow
9AllowedIPs = 10.88.88.105/32
Kemudian konfigurasi Nginx di VPS server sebagai reverse proxy ke LXC server, kurang lebih konfigurasi Nginx saya sebagai berikut:
1upstream immich_app {
2 server 10.88.88.105:443;
3}
4
5server {
6 listen 80;
7 listen 443 ssl;
8 server_name i.arch.or.id;
9
10 # Self-signed certificates
11 ssl_certificate /etc/nginx/certs/fullchain.pem;
12 ssl_certificate_key /etc/nginx/certs/privkey.pem;
13
14 # Acme challenge handler
15 location /.well-known/acme-challenge/ {
16 allow all;
17 proxy_set_header Host $host;
18 proxy_set_header X-Real-IP $remote_addr;
19 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
20 proxy_set_header X-Forwarded-Proto https;
21
22 # This avoid SSL_do_handshake() failed on HTTPS upstream
23 proxy_ssl_name $host;
24 proxy_ssl_server_name on;
25 proxy_ssl_verify off;
26
27 proxy_pass https://immich_app;
28 }
29
30 keepalive_timeout 70;
31 sendfile on;
32 client_max_body_size 100m;
33
34 location / {
35 proxy_set_header Host $host;
36 proxy_set_header X-Real-IP $remote_addr;
37 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
38 proxy_set_header X-Forwarded-Proto https;
39
40 # This avoid SSL_do_handshake() failed on HTTPS upstream
41 proxy_ssl_name $host;
42 proxy_ssl_server_name on;
43 proxy_ssl_verify off;
44
45 # enable websockets: http://nginx.org/en/docs/http/websocket.html
46 proxy_http_version 1.1;
47 proxy_set_header Upgrade $http_upgrade;
48 proxy_set_header Connection "upgrade";
49 proxy_redirect off;
50
51 proxy_pass https://immich_app;
52 }
53}
Bisa dilihat bahwa Nginx di VPS server menggunakan Self-signed certificates.
Hal ini tidak menjadi masalah karena kita sudah mengkonfigurasi Cloudflare
SSL/TLS encryption mode ke Full
.
Dengan konfigurasi diatas, HTTP request dari internet akan melewati Cloudflare dan menggunakan sertifikat SSL yang valid dari Cloudflare. Request dilanjutkan ke VPS server dan kemudian diteruskan ke LXC server melalui WireGuard VPN tunnel.
Lokal LXC: WireGuard, Immich (Docker), Nginx, Certbot
Install WireGuard dan buat konfigurasi supaya bisa terhubung ke WireGuard server di VPS. Berikut ini contoh konfigurasi WireGuard di LXC server saya:
1[Interface]
2PrivateKey = SomeRandomStringThatShouldBePrivateII
3Address = 10.88.88.105/22
4
5# VPS server
6[Peer]
7PublicKey = SomeRandomStringThatPublicMayKnowII
8AllowedIPs = 10.88.88.51/32
9Endpoint = 154.26.xxx.xxx:51822
10PersistentKeepalive = 15
Kemudian, install Immich dengan mengikuti proses instalasi Immich menggunakan
Docker dari situs resminya. Secara default, Immich akan
menggunakan TCP port 2283
.
Buat konfigurasi Nginx virtual host untuk Immich. Nginx di LXC ini akan berfungsi sebagai reverse proxy dan menghandle Acme challenge sehingga server LXC memiliki sertifikat yang valid. Berikut ini adalah contoh konfigurasi Nginx virtual host untuk Immich di server LXC lokal:
1upstream immich_app {
2 server 127.0.0.1:2283;
3}
4
5server {
6 listen 80;
7 server_name i.arch.or.id;
8 root /srv/http/default;
9
10 location /.well-known/acme-challenge/ {
11 allow all;
12 }
13 location / { return 301 https://$host$request_uri; }
14}
15
16server {
17 listen 443 ssl;
18 server_name i.arch.or.id;
19 ssl_certificate /etc/nginx/certs/fullchain.pem;
20 ssl_certificate_key /etc/nginx/certs/privkey.pem;
21
22 # allow large file uploads
23 client_max_body_size 50000M;
24
25 location / {
26 # Set headers
27 proxy_set_header Host $http_host;
28 proxy_set_header X-Real-IP $remote_addr;
29 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
30 proxy_set_header X-Forwarded-Proto $scheme;
31
32 # enable websockets: http://nginx.org/en/docs/http/websocket.html
33 proxy_http_version 1.1;
34 proxy_set_header Upgrade $http_upgrade;
35 proxy_set_header Connection "upgrade";
36 proxy_redirect off;
37
38 proxy_pass http://immich_app;
39 }
40}
Dari konfigurasi Nginx diatas, perlu diperhatikan bahwa untuk konfigurasi awal saya masih menggunakan Self-signed certificate. Langkah selanjutnya adalah melakukan request sertifikat SSL menggunakan Certbot.
Catatan: Sebelum melakukan request serifikat SSL, pastikan koneksi antara VPS server dan LXC melalui WireGuard tunnel berjalan dengan baik. Begitu pula dengan konfigurasi Nginx baik di VPS server dan LXC server.
Install certbot Nginx plugin. Di Ubuntu, Anda bisa menginstall cerbot Nginx
plugin menggunakan sudo apt install python3-certbot-nginx
. Setelah Certbot
Nginx plugin terinstall, lakukan request sertifikat SSL dari XLC server:
1sudo certbot --nginx -d i.arch.or.id
Ubah i.arch.or.id
ke (sub)domain milik Anda.
LAN: Lokal DNS resolver
Langkah terakhir adalah mengkonfigurasi perangkat-perangkat di jaringan LAN
supaya subdomain i.arch.or.id
mengarah ke IP lokal server LXC
(192.169.2.105). Cara paling efektif adalah menggunakan lokal DNS resolver
yang bisa digunakan oleh seluruh perangkat di jaringan LAN. Untuk konfigurasi
DNS resolver akan sangat bervariasi tergantung seperti apa jaringan LAN
masing-masing.
Untuk jaringan LAN saya, saya mempunyai dua buah DNS resolver. DNS resolver pertama berada di Router MikroTik, dan resolver kedua menggunakan AdGuard Home yang berjalan di Linux Container. AdGuard home disini saya gunakan juga sebagai DHCP server untuk jaringan lokal saya.
Berikut capture konfigurasi DNS resolver di MikroTik router dan AdGuard Home saya:
Dengan konfigurasi tersebut, seluruh perangkat yang ada di jaringan lokal
menggunakan DHCP akan langsung akan menggunakan IP 192.168.2.105
ketika
mencoba mengakses subdomain i.arch.or.id
.
limitasi
- Karena maksimum upload di Cloudflare hanya 100MB per request (untuk free version), maka proses sinkronisasi Immich dari internet kemungkinan besar banyak yang gagal, terutama saat sinkronisasi video.