처음부터 시작: 1Panel로 Mix Space 백엔드 배포하기
Note이것은 「Mix Space + Yohaku 배포 시리즈」의 첫 번째 글로, 백엔드(Core) 설치에 초점을 맞춥니다. 프론트엔드 테마 Yohaku의 배포는 두 번째 글로 이동해 주세요.
Mix Space는 현대적인 프론트엔드·백엔드 분리형 개인 블로그 시스템입니다. 백엔드 Core는 RESTful API, 스케줄 작업, 백업, 서버리스 함수 등 모든 서비스를 제공하며, 시스템 전체가 조용히 돌아가는 심장과 같습니다. 프론트엔드 테마는 이와 분리되어 있어 자유롭게 조합할 수 있습니다.
이 글에서는 1Panel 패널을 이용해 Mix Space 백엔드를 내 서버에 올리는 방법을 소개합니다. 복잡한 설정 없이 차근차근 따라 하기만 하면 됩니다.
1단계 · 1Panel 패널 설치
1Panel은 현대적인 오픈소스 리눅스 서버 관리 패널로, 인터페이스가 깔끔하고 조작이 직관적입니다. 이 패널을 사용하면 이후의 컨테이너 관리, 파일 업로드, 리버스 프록시 설정이 훨씬 수월해집니다.
설치 전 간단한 확인 사항
| 확인 항목 | 요구 사항 |
|---|---|
| 운영체제 | 주요 리눅스 배포판(Debian / Ubuntu / CentOS 등) |
| 서버 아키텍처 | x86_64, aarch64, armv7l 등 지원 |
| 가용 메모리 | 1GB 이상 권장 |
| 네트워크 환경 | 인터넷 정상 접속 가능 |
| 브라우저 | Chrome, Firefox, Edge 등 현대적인 브라우저 |
한 줄 명령어로 설치 완료
SSH로 서버에 접속한 후 다음을 실행하세요.
bash -c "$(curl -sSL https://resource.fit2cloud.com/1panel/package/v2/quick_start.sh)"
명령줄 안내에 따라 진행하고 설치가 완료될 때까지 기다립니다. 성공하면 콘솔에 아래와 같은 접속 정보가 출력됩니다.
패널 주소: http://서버IP:포트/보안_입구
보안 입구를 잊으셨나요? SSH로 서버에 접속하여 다음 명령어를 실행하면 entrance 필드 값이 입구 경로입니다.
1pctl user-info
만약 Docker 설치에 실패했다면, 아래 명령을 먼저 실행하여 문제를 해결하세요.
bash <(curl -sSL https://linuxmirrors.cn/docker.sh)
2단계 · 1Panel로 Mix Space 설치하기
2.1 애플리케이션 패키지 다운로드
아래 저장소에서 mxspace.zip 파일을 다운로드하여 준비하세요.
2.2 애플리케이션 패키지 업로드
1Panel 패널에 로그인한 후 왼쪽 메뉴에서 호스트 → 파일로 이동하여 다음 경로로 이동합니다.
/opt/1panel/resource/apps/local
업로드 버튼을 클릭하여 방금 다운로드한 mxspace.zip 파일을 선택합니다.
2.3 압축 해제, 경로에 주의!
업로드가 완료되면 mxspace.zip을 클릭하고 압축 해제를 선택합니다.
이 단계는 반드시 주의하세요!
압축 해제 시 대상 경로를 다음과 같이 직접 완성시켜 주어야 합니다.
/opt/1panel/resource/apps/local/mxspace
경로를 잘못 입력하면 파일이 엉뚱한 디렉터리에 흩어져 앱 스토어에서 이 로컬 앱을 인식하지 못합니다.
2.4 로컬 앱 동기화
1Panel 앱 스토어로 이동하여 우측 상단의 로컬 앱 동기화 버튼을 클릭합니다. 잠시 후 검색창에 mxspace를 입력하면 방금 추가한 앱이 나타납니다.
설치를 클릭하여 설정 페이지로 진입합니다.
2.5 설치 설정 항목 작성
설치 페이지에는 읽기 전용 안내 세 줄과 다섯 개의 설정 항목이 있으며, 위에서부터 순서대로 작성합니다.
Note페이지 상단에 회색으로 표시된 세 줄의 「📌」 안내 문구는 JWT 비밀 키 요구 사항, 도메인 형식, 암호화 기능 주의 사항을 각각 설명하고 있습니다. 참고용이므로 수정할 필요 없이 넘어가면 됩니다.
🔑 JWT 비밀 키 (JWT Secret)
이것은 백엔드 서비스의 핵심 보안 자격 증명으로, 길이는 16자 이상 32자 이하여야 합니다. 임의로 생성한 강력한 비밀번호를 사용하는 것을 권장하며, 터미널에서 다음 명령어를 실행할 수 있습니다.
openssl rand -base64 24
생성된 결과를 여기에 입력하고 안전하게 보관하세요. 이 값은 블로그 시스템의 열쇠와 같아서 분실 시 재설정해야 하므로 번거로움이 생깁니다.
🌐 허용된 오리진 (Allowed Origins)
백엔드 API에 접근을 허용할 프론트엔드 도메인을 입력하며, 여러 도메인은 쉼표로 구분합니다. 예시 형식:
localhost:*,당신의_테마_프론트엔드_도메인
Yohaku 프론트엔드를 배포할 때는 여기에 Yohaku가 위치한 도메인을 입력해야 합니다. 아직 확실하지 않다면 우선 localhost:*로 입력하고, 이후 설치된 앱의 설정 페이지에서 수정할 수 있습니다.
🔒 암호화 사용 여부 (Enable Encryption)
드롭다운 선택이며 기본값은 비활성화(권장) 입니다.
🗝️ 암호화 키 (Encryption Key)
위 항목에서 「활성화」를 선택한 경우에만 입력해야 합니다. 키는 반드시 64자의 소문자와 숫자여야 하며, 다음 명령어로 생성할 수 있습니다.
openssl rand -hex 32
암호화를 비활성화한 경우 이 항목은 비워 둡니다.
🔢 HTTP 포트
기본값은 2333이며 일반적으로 변경하지 않아도 됩니다. 포트 충돌이 있을 경우 다른 사용 가능한 포트로 변경할 수 있습니다.
Note포트 외부 접근을 직접 허용하기보다는 다음 단계에서 리버스 프록시를 통해 서비스를 제공하는 것이 더 안전하고 모범적인 방식입니다.
2.6 설치 시작 🎉
설정 내용을 확인한 후 설치 시작을 클릭합니다.
1Panel이 자동으로 innei/mx-server, mongo:7, redis:alpine 세 개의 이미지를 풀 받아 오케스트레이션하여 실행합니다. 최초 설치 시 이미지를 내려받아야 하므로 몇 분 정도 기다려 주세요.
상태가 실행 중(Running)으로 표시되면 Mix Space 백엔드가 조용히 가동되기 시작한 것입니다 🌿
3단계 · 리버스 프록시 및 HTTPS 설정
포트를 직접 노출하는 방식은 안전하지도 않고 깔끔하지도 않습니다. Nginx 리버스 프록시를 통해 서비스를 도메인에 연결하고 HTTPS를 더해 주어야 비로소 완성됩니다.
여기에서 완전한 Nginx 설정을 제공합니다. 이 설정은 흥미로운 구조를 가지고 있는데, 프론트엔드(Yohaku, 포트 2323)와 백엔드(Mix Space Core, 포트 2333)의 라우팅을 동일한 server 블록 안에 작성하여 하나의 도메인으로 외부에 서비스합니다. 방문자가 블로그에 접속하면, 프론트엔드 페이지와 백엔드 API가 보이지 않는 곳에서 각자의 역할을 수행하며 바깥에는 깔끔한 도메인만 드러납니다.
1Panel의 웹사이트 → OpenResty → 설정 파일에서 입력하거나, 서버의 Nginx 설정 파일을 직접 편집하여 다음 내용을 넣어주세요.
사용 전에 아래 내용을 자신의 값으로 교체하세요:
당신의_도메인→ 실제 도메인으로 교체, 총 7군데당신의_서브넷→ 실제 서브넷 CIDR로 교체, 총 1군데당신의_서버IP→ 실제 서버 IP로 교체, 총 1군데 (set_real_ip_from필드)- SSL 인증서 경로 → 실제 인증서 경로로 교체 (
ssl_certificate및ssl_certificate_key) baidu_verify_*.html→ Baidu 사이트 인증이 필요 없다면 해당 location 블록을 삭제하세요.
server {
# IPv4/IPv6 HTTP 및 HTTPS 포트 수신
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
server_name 당신의_도메인;
index index.php index.html index.htm default.php default.htm default.html;
root /www/sites/당신의_도메인/index;
# 로그 경로
access_log /www/sites/당신의_도메인/log/access.log main;
error_log /www/sites/당신의_도메인/log/error.log;
error_page 404 /404.html;
# CDN/프록시에서 실제 클라이언트 IP 가져오기
real_ip_recursive on;
set_real_ip_from 당신의_서브넷(예:172.19.0.0/16);
set_real_ip_from 당신의_서버IP;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
# 백엔드로 클라이언트 정보 전달
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;
# SSL 인증서 및 보안 설정
ssl_certificate /www/sites/당신의_도메인/ssl/fullchain.pem;
ssl_certificate_key /www/sites/당신의_도메인/ssl/privkey.pem;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HTTP/2 및 HSTS 활성화
http2 on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# Baidu 인증 파일 직접 반환
location = /baidu_verify_codeva-46XKS9HVjs.html {
root /www/sites/당신의_도메인/index;
default_type text/plain;
try_files $uri =404;
}
# 루트 경로: 잘못된 매개변수 제거 후 리다이렉트; 그렇지 않으면 정상 프록시
location = / {
if ($args ~* "error=please_restart_the_process") {
return 301 $scheme://$host;
}
proxy_pass http://127.0.0.1:2323;
}
# 민감한 파일 숨기기
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) {
return 404;
}
# ACME 인증 디렉터리
location ^~ /.well-known/acme-challenge {
allow all;
root /usr/share/nginx/html;
}
# .well-known 아래 동적 파일 접근 차단
location ~ ^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$ {
return 403;
}
# WebSocket 프록시
location /socket.io {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_buffering off;
proxy_pass http://127.0.0.1:2333/socket.io;
}
# API, 렌더링, 프록시 포워딩
location /api/v3 { proxy_pass http://127.0.0.1:2333/api/v3; }
location /render { proxy_pass http://127.0.0.1:2333/render; }
location /proxy { proxy_pass http://127.0.0.1:2333/proxy; }
location /qaqdmin { proxy_pass http://127.0.0.1:2333/proxy/qaqdmin; }
# 그 외 경로는 버퍼링 최적화와 함께 백엔드로 전달
location / {
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_pass http://127.0.0.1:2323;
}
# HTTP 자동 HTTPS 리다이렉트
if ($scheme = http) {
return 301 https://$host$request_uri;
}
error_page 497 https://$host$request_uri;
}
설정 저장 후 nginx -t로 문법을 검사하고 nginx -s reload로 다시 로드하면 적용됩니다.
라우팅 로직 한눈에 보기:
| 경로 접두사 | 프록시 대상 | 설명 |
|---|---|---|
/api/v3 | 백엔드 :2333 | Mix Space REST API |
/socket.io | 백엔드 :2333 | WebSocket 실시간 푸시 |
/render | 백엔드 :2333 | 서버 사이드 렌더링 인터페이스 |
/proxy | 백엔드 :2333 | 프록시 및 관리자 백엔드 진입점 |
/qaqdmin | 백엔드 :2333 | 관리자 백엔드 바로 가기 진입점 |
| 그 외 모든 경로 | 프론트엔드 :2323 | Yohaku 페이지 |
즉, 하나의 도메인만 있으면 프론트엔드 블로그와 백엔드 관리 기능을 모두 동일한 진입점 아래에서 깔끔하고 우아하게 이용할 수 있습니다.
설정이 완료되면 백엔드 관련 주소는 다음과 같습니다(추후 Yohaku 배포 시 사용합니다):
백엔드 API 주소: https://당신의_도메인/api/v2
백엔드 게이트웨이 주소: https://당신의_도메인
관리자 백엔드 주소: https://당신의_도메인/qaqdmin
이 주소들을 꼭 기록해 두세요.
4단계 · 관리자 백엔드 초기화
리버스 프록시 설정이 끝나면 브라우저에서 관리자 백엔드에 접속합니다.
https://당신의_도메인/qaqdmin
최초 방문 시 관리자 계정 생성, 사이트 기본 정보 입력 등 초기화 과정이 안내되며, 화면의 지시에 따라 진행하면 됩니다.
자주 묻는 질문
Q: 설치 후 컨테이너가 계속 재시작되고 정상적으로 시작되지 않나요?
대부분 MongoDB나 Redis의 헬스 체크가 아직 통과되지 않았기 때문입니다. 이들은 완전히 준비되는 데 약간의 시간이 필요하며, Core 컨테이너가 자동으로 재시도합니다. 약 1분 정도 기다리면 보통 자체 복구됩니다. 계속 비정상 상태라면 1Panel의 컨테이너 로그에서 구체적인 오류 메시지를 확인해 보세요.
Q: JWT 비밀 키를 저장하는 것을 잊었습니다. 어떻게 하나요?
1Panel 앱 스토어의 설치된 앱 목록에서 mxspace의 편집 또는 설정을 클릭하면 현재 환경 변수 값을 확인할 수 있습니다.
Q: 허용된 오리진을 변경하려면 어떻게 하나요?
설치된 앱의 설정 페이지에서 ALLOWED_ORIGINS 환경 변수를 수정하고 저장한 후 컨테이너를 재시작하면 적용됩니다.
Q: 데이터는 어디에 저장되나요?
모든 데이터는 /opt/1panel/apps/local/mxspace/mxspace/data/ 디렉터리에 영구 저장되며, MongoDB 데이터, Redis 데이터 및 mx-space 런타임 파일이 포함됩니다. 이 디렉터리를 정기적으로 백업하면 되고, 1Panel 스냅샷과 함께 백업할 수도 있습니다.
참고 자료
백엔드는 이제 안정적으로 자리 잡았습니다 🌱 이제 두 번째 글로 이동하여 Yohaku라는 아름다운 겉옷을 입혀 주세요.