| 파일 | 트리 탐색·이름으로 거르기·업로드·다운로드(진행률·취소·끊기면 이어받기)·폴더째 전송·이름 변경·삭제·권한(체크박스 + chmod 755 직접 입력). 편집기가 못 여는 파일은 읽기 전용으로 — 이미지는 그리고, 나머지는 앞부분을 hex로 |
| 코드 편집 | 트리 옆 분할 뷰 · 파일 탭 · 문법 강조 24종 · 찾기/바꾸기 · 저장 전 diff · 원자적 저장(임시 파일 + rename). 서버에도 클라이언트에도 편집기를 깔지 않습니다 |
| 서비스 | systemd 유닛 / Windows 서비스. 목록·필터·시작/중지/재시작·자동 시작 설정·실시간 로그 보기(Linux) |
| 프로세스 | 작업 관리자식 테이블. 정렬·검색·트리 보기·종료(TERM→KILL 2단계)·우선순위 변경 |
| 컨테이너 | Docker·Podman 카드. 시작/중지/재시작/삭제·실시간 로그 보기·이미지/볼륨 정리. Compose로 띄운 것은 프로젝트별로 묶여 전체 시작·중지·재시작 |
| 네트워크 | 인터페이스와 열린 포트. 외부에 노출된 포트를 구분해서 표시. sshd 설정 점검 |
| 세션 | 이 서버에 누가 붙어 있는지. 접속별로 끊기. 성공한 접속은 보안 탭에도 올라오고, 처음 보는 주소는 거기서 표시됩니다. 접속 이력과 실패 시도 — 성공은 wtmp, 실패는 저널에서 읽습니다. 실패는 하루 수천 건이라 목록이 아니라 IP·계정별 요약입니다 |
| 스케줄 | systemd 타이머. 다음·마지막 실행 시각 |
| 터미널 | xterm.js PTY, 탭 여러 개. code . · vi foo.conf를 앱이 가로채 파일 탭에서 엽니다. 서버로 보내지 않으므로 VS Code나 vi가 없어도 됩니다 |
| 모니터링 | 요약 바는 한눈에, 모니터링 탭은 대시보드로. CPU 시간을 사용자·커널·I/O 대기·스틸 시간으로 구분해 보여줍니다 — 90%가 전부 I/O 대기면 디스크가, 전부 스틸 시간이면 하이퍼바이저가 문제입니다. 코어별 사용률, 메모리의 캐시·버퍼 분리, NVIDIA 카드가 있으면 GPU 사용률·팬·온도·VRAM (nvidia-smi) |
| 인프라 지표 | inode (용량은 남았는데 파일을 못 만드는 상태), 네트워크 오류·버림 카운터, 디스크 I/O, PSI (사용률이 아니라 「얼마나 기다렸는가」), 실행 대기·I/O 블록, 열린 FD. 전부 /proc과 df를 읽는 값이라 서버에 설치하는 것은 여전히 없습니다 |
| 추세 | 보고 있는 동안의 CPU·메모리·GPU를 시간축으로. 앱이 안 보던 구간은 선을 끊어 표시합니다 — 없는 기록을 이어 그리지 않습니다 |
| 명령 이력 | 터미널 탭 옆 패널. 어느 폴더에서 무엇을 실행했나를 최근순 폴더 카드로 — 최근 작업 · 전체 · 원본 세 갈래. 세 가지 데이터 출처(sudo 저널 · 이 앱의 터미널 · 셸 이력 파일)를 섞지 않고 각각 표시합니다. sudo 저널의 경로는 기록이라 확실하고, 이력 파일의 경로는 cd를 되짚은 것이라 카드마다 「정확」·「추정」을 적습니다. 되짚은 곳이 실제로 있는지 서버에 확인하므로, 세션 이음매 때문에 project/project/project 같은 없는 경로가 생기지 않습니다. 셸 이력은 서버별로 켜야 읽고, 비밀번호처럼 보이는 것은 Go에서 가립니다 |
| 안 보던 사이 | 호스트를 열면 마지막으로 본 이후 무엇이 바뀌었는지 한 줄로. 모니터링 탭에는 보안 업데이트 개수와 재부팅 필요 여부 — 파일 두 개를 읽을 뿐이라 root도 명령도 필요 없습니다 |
| 보안 | 무엇이 서버를 보호하고 있고, 그 설정이 실제로 적용돼 있는가. 방화벽(ufw·nftables·iptables·firewalld)과 fail2ban을 유닛·설정 파일·커널 세 곳에서 읽고 어긋나면 그것을 보여줍니다 — 유닛이 켜졌는데 방화벽이 꺼진 서버가 실재합니다. 버린 패킷 수와 마지막으로 본 뒤의 증가, 차단 목록(fail2ban 것과 직접 넣은 것을 갈라서), 24시간 실패 추이에 밴 시점 표시, 아직 안 막힌 공격자. 설정 파일의 값과 현재 적용된 값을 비교해 fail2ban 재시작이 필요한 상태를 잡습니다 |
| 이벤트 | 무슨 일이 언제 있었나. OOM killer, 유닛 실패, 코어 덤프, 재시작 예약, 재부팅 경계. systemd 저널을 읽되 문구가 아니라 MESSAGE_ID로 갈라내므로 서버 언어와 무관합니다 |
| Command Log | GUI가 실행한 모든 명령을 실시간으로 표시. 클릭하면 복사됩니다 |
| 설정 동기화 | 호스트 목록과 승인 정책을 암호화된 파일 하나로 내보내고, 다른 기기에서 읽습니다. Google Drive·Dropbox·USB 어디에 두어도 됩니다 — 계정도 서버도 없습니다. 비밀번호·개인키·sudo 암호는 파일에 들어가지 않습니다. 정책이 느슨해지는 항목은 받는 기기에서 사람이 확인해야 적용됩니다 |
| MCP | Claude Code·Claude Desktop이 이 앱을 통해 서버를 조회하고 바꿉니다. 서버별 opt-in, 변경은 승인, 되돌리기 가능 |
| 접속 | 비밀번호·키·에이전트·2FA. ~/.ssh/config 가져오기. ProxyJump 로 경유 서버 한 단계 |
| 언어 | 한국어·영어. 고른 적이 있으면 그 언어로, 없으면 OS 언어로 시작합니다. 사이드바 아래 KO/EN로 바꿉니다 |
| 테마 | 라이트·다크. 고른 적이 있으면 그 테마로, 없으면 OS 설정으로 시작합니다. 사이드바 아래에서 바꿉니다 |
⌘B 한 번으로 왼쪽이 52px 아이콘 줄로 접힙니다. 접어도 서버와 화면은 그대로 옮겨 다닐 수 있습니다. 위쪽에 있던 두 줄도 한 줄로 합쳐서, 1440×900에서 편집기가 823×691 → 1071×748이 됐습니다 — 넓이로 41% 늘었습니다.
- 가로 탭 아홉 개가 왼쪽 세로 묶음으로. 작업 · 시스템 · 관측으로 갈랐습니다. 지원하지 않는 화면을 비활성화하는 대신 점으로 표시합니다 — 회색은 이유를 말하지 않고, 그 화면 자신이 이유를 설명합니다
- 파일 탭을 키보드만으로.
↑↓선택,Enter열기(폴더면 들어가고 파일이면 편집기),F2이름 변경,⌘←⌘→뒤로·앞으로,⌘↑상위 폴더. 윈도우는Alt조합입니다 - 잠금은 탭이 아니라 연결마다 하나. 보안 탭에서 열면 네트워크 탭의 프로세스 이름도 같이 보입니다 — 같은 권한을 두 번 묻지 않습니다
Escape로 모든 대화상자가 닫힙니다. 되돌릴 수 없는 것은 바깥을 눌러도 닫히지 않습니다 — 빗나간 클릭은 대답이 아닙니다- 라이트 모드에서 안 보이던 글자들. 차트 눈금은 9px에 대비 2.36이라 사실상 보이지 않았습니다. 색을 다시 잡았고, 이제 테스트가 그걸 지킵니다
- 시각 표기 통일 —
2026-09-09 12:23. 서버 로그가 찍는 모양 그대로라 옮겨 읽을 일이 없습니다
켠 지 10초 뒤에 한 번 확인하고, 새 버전이 있으면 같은 버튼이 「2.2.0 업데이트」가
됩니다. 누르면 내려받아 SHA256SUMS.txt와 대조한 뒤 「업데이트 적용」이 되고,
적용은 사람이 누를 때만 합니다. 서명 없는 바이너리를 조용히 갈아 끼우는 것은
공급망 공격과 모양이 같습니다. OS 키체인에 저장한 비밀번호는 그대로 남습니다.
타이머는 없습니다. 하나 하려고 열었다 닫는 앱이 오후 내내 github을 두드릴 이유가 없습니다.
리눅스와 같은 질문에 답하지만, 근거가 하나도 겹치지 않습니다.
터미널 셸 고르기 — cmd · PowerShell · WSL. sshd는
HKLM\SOFTWARE\OpenSSH\DefaultShell이 말하는 것을 내주고 기본 설치에서는
cmd 입니다. WSL 배포판은 wsl -l이 아니라 레지스트리(Lxss)에서 읽습니다 —
배포판이 없는 기계에서 그 명령은 도움말을 출력하고 0으로 끝나기 때문입니다.
실측한 기계에서 98줄이었고, 줄마다 배포판으로 읽으면 그게 다 메뉴에 올라옵니다.
실행할 명령 없이 wsl.exe -d X만 실행하는 일은 절대 없습니다. ConPTY 위에서 그것은
응답하지 않고, 시스템을 재부팅할 때까지 LxssManager가 응답하지 않을 수 있습니다.
항상 실행할 명령을 함께 줍니다.
깨우는 확인은 이미 도는 것이 있으면 기다리고 새로 만들지 않습니다 — 누를 때마다
하나씩 남기던 것이 바로 그 굳힘의 원인이었습니다.
세션 — 세션은 실제 계정이 소유한 sshd 자식입니다. SYSTEM이 가진 것은 리스너와
연결별 부모이고, sshd_NNNN이 가진 것은 인증 전의 낯선 사람입니다. 접속 주소는
Get-NetTCPConnection이 22번 포트의 모든 연결을 리스너에게 돌리므로 소켓 표에서
못 얻고, 시각이 찍힌 OpenSSH 이벤트 로그에서 프로세스와 짝지어 옵니다.
세션을 끊을 때는 taskkill /F /T로 프로세스 트리 전체를 종료합니다. 프로세스 하나만
종료하면 그 아래 셸이 살아남고 연결도 끊기지 않습니다.
보안 — 방화벽 프로필 셋(지금 네트워크가 속한 것을 표시), 포트를 여는 인바운드 규칙
(실제로 수신 중인 프로세스가 있는 규칙을 위에), 계정 잠금 정책, Defender, 그리고 접속을
시도한 원격 주소. 잠금 정책은 net accounts가 아니라 secedit /export로 읽습니다. 앞의
것은 출력이 번역돼 있어서 한국어 기계를 정책 없는 기계로 읽습니다.
Linux의 fail2ban 자리에는 계정 잠금이 오는데, 그 한계도 화면에 적습니다. 잠기는 것은 계정이지 주소가 아니어서, 계정 이름을 바꿔 가며 시도하는 공격에는 걸리지 않습니다.
로그가 실제로 덮는 기간을 적습니다. Windows의 OpenSSH 로그는 1MB 순환입니다. 암호 대입 공격을 받던 실제 서버에서 2,343건이 77분치였습니다. 이것을 「최근 24시간」이라고 적으면 온종일 이어진 공격이 방금 시작된 것처럼 보이므로, 로그에 남아 있는 가장 오래된 시각을 대신 적습니다.
채울 값이 없는 열은 그리지 않습니다. Windows에는 단말도 유휴 시간도 없고, utmp를 쓰지 않는 컨테이너도 마찬가지입니다. 모든 행이 「—」인 열은 정보가 빠진 표처럼 보입니다.
아직 안 되는 것 — 이벤트 탭. 윈도우 이벤트 로그가 journald 자리에 대응되지만 읽는 코드가 없습니다.
재시작이 권한 부족으로 거부되자 물어봅니다. 실행된 명령은 그대로 보이고, 비밀번호는 stdin으로 가서 보이지 않습니다.
운영 서버를 만지는 GUI는 결국 "믿어달라"고 요구하는 셈입니다. LiteDeck은 방금 무엇을 실행했는지 정확히 보여주는 것으로 그 신뢰를 얻습니다.
$ systemctl list-units --type=service --all --output=json 120ms
$ journalctl -u myapp.service -n 200 -f --no-pager -q
$ sudo -S -p '' -- systemctl restart -- myapp.service 310ms
$ powershell -EncodedCommand ⟨utf8 prelude⟩ Restart-Service -Name 'Spooler' -Force
비밀번호는 표준 입력으로 전달되므로 명령줄을 그대로 보여줘도 안전합니다. 이 기록은 로컬에만 남고 외부로 나가지 않습니다.
터미널에 code .을 치면 그 줄이 서버로 가기 전에 앱이 가로채 파일 탭으로 옵니다. vi로 새 파일을 열면 편집기 탭이 열립니다. 서버에는 VS Code도 vi도 필요 없습니다.
원격 파일을 고치려면 보통 둘 중 하나를 깝니다. 서버에 vscode-server(수백 MB)를 올리거나,
서버의 vi·nano를 터미널로 쓰거나. LiteDeck은 둘 다 안 합니다.
- 서버 쪽. 아무것도 필요 없습니다. 파일은 SSH가 이미 제공하는 SFTP로 읽고 씁니다. 서버에 편집기가 없어도, 있어도 상관없습니다
- 클라이언트 쪽. VS Code를 설치할 필요가 없습니다. 편집기가 앱 안에 들어 있습니다 (CodeMirror, 문법 24종). 첫 파일을 열 때 로드되므로 디렉터리만 보다 끄면 비용이 없습니다
터미널에서 code .이나 vi foo.conf를 치면 앱이 그 줄을 서버로 보내기 전에 가로채
파일 탭으로 이동합니다. 서버는 이 기능의 존재를 모릅니다. 그래서 서버에 VS Code도 vi도
없어도 되고, 반대로 서버 쪽에서 무언가 열리는 일도 없습니다.
트리에서 파일을 열면 문법 강조가 붙은 편집기가 오른쪽에 열립니다. 저장을 누르면 서버에 지금 들어 있는 내용과의 diff가 먼저 뜹니다.
확인하고 넘어가면 같은 디렉터리의 임시 파일에 쓴 뒤 rename으로 갈아끼웁니다. 저장이
중간에 끊겨도 원본이 반토막 나지 않고, 성공하면 임시 파일은 남지 않습니다. rename이
실패하면 임시 파일을 지우지 않고 그 경로를 화면에 알려 줍니다 — 편집한 내용을 잃는 것보다
낫기 때문입니다. 서버에 무언가를 쓰는 유일한 예외가 이 임시 파일입니다.
대비: VS Code Remote-SSH는 서버에 서버를 설치합니다. 저사양 VPS에서
vscode-server가 메모리를 잡아먹는 것은 잘 알려진 문제입니다. 본격 원격 IDE가 필요하면 그쪽이 정답이고, 설정 파일 하나 고치자고 수백 MB를 올리기 싫을 때 이쪽이 답입니다.
주소창 옆 칸에 이름 일부를 치면 목록이 좁혀집니다 (⌘F · Ctrl+F).
서버에는 아무것도 묻지 않습니다. 앱이 이미 받아 둔 목록만 거르므로, 아무리 빨리 입력해도 서버가 하는 일은 없습니다. 한 번 열어 본 폴더는 접어 두었어도 검색 대상이라, 접힌 폴더 안에 있는 파일도 경로째 올라옵니다.
대신 한 번도 열어 보지 않은 폴더는 보지 않습니다. 원격에서 find를 돌리면 그 폴더까지
찾을 수 있지만, 그건 서버에 추가 부하를 주는 작업이고 이 도구가 하지 않기로 한 쪽입니다. 일치가
없을 때 화면이 그렇게 적어 둡니다.
디렉터리를 통째로 올리고 내립니다. 큐에는 파일마다가 아니라 트리 하나당 한 줄이 생기고, 그 줄이 몇 번째 파일을 옮기는 중인지 보여줍니다.
서버 쪽 비용을 신경 썼습니다. 트리를 훑는 것도 옮기는 것도 SFTP뿐입니다 — find도
tar도 돌리지 않으므로 서버에 프로세스가 뜨지 않습니다. 훑는 단계는 작업 안에서 돌아서
탐색 단계에서도 취소할 수 있습니다. 실수로 큰 디렉터리를 골랐을 때 멈출 방법이 있다는 뜻입니다.
끊긴 전송은 이어받습니다. SFTP는 읽기·쓰기마다 절대 오프셋을 실어 보내는 프로토콜이라, 이어붙이는 것 자체는 seek 한 번입니다. 어려운 쪽은 이어붙일 대상이 정말 같은 파일인가 이고, LiteDeck은 이렇게 확인합니다:
- 원본의 크기와 수정 시각이 전송을 시작할 때와 같은지
- 이어붙일 지점 바로 앞 64KB를 양쪽에서 다시 읽어 비교
두 번째가 필요한 이유는 SFTP가 수정 시각을 초 단위로만 전달하기 때문입니다. 같은 1초 안에 같은 길이로 다시 만들어진 파일은 크기와 시각만으로는 구분되지 않습니다. 이음매의 바이트가 다르면 이어받기를 거부하고 받다 만 파일을 지웁니다.
이 검사는 이음매를 봅니다. 이미 받은 구간 전체를 검증하려면 원본을 처음부터 다시 읽어야 하는데, 그건 이어받기가 피하려던 바로 그 일입니다. 그래서 길이가 정확히 같고 64KB 창 바깥만 달라진 원본은 통과할 수 있습니다. 한계를 적어두지 않으면 그만큼 더 믿게 되므로 적어둡니다.
폴더 전송도 이어받습니다. 다만 단위가 파일입니다. 트리는 파일마다 최종 이름으로 곧장 쓰이므로, 이어받기는 이미 도착한 파일을 건너뛰고 옮기던 파일 하나만 처음부터 다시 씁니다. 이어붙일 이음매가 없어서 위의 64KB 검사도 여기서는 필요 없습니다.
건너뛰는 파일은 믿고 넘어갑니다. 끊긴 뒤에 원본이 바뀌었다면 그 파일은 옛 사본으로 남습니다. 크기를 비교해 건너뛰는 방식을 쓰지 않는 것도 같은 이유인데, 길이가 같고 내용만 바뀐 파일은 크기로 가려낼 수 없기 때문입니다. 대신 번호만은 보장합니다 — 처음 훑을 때 만든 목록을 그대로 다시 쓰므로, 도중에 파일이 생기거나 지워져도 번호가 밀려 엉뚱한 파일을 건너뛰는 일은 없습니다.
Compose로 띄운 컨테이너는 프로젝트별로 묶여서 나오고, 묶음 머리에 전체 동작 버튼이 붙습니다.
| 누르는 곳 | 실행되는 것 |
|---|---|
| 카드의 시작·중지·재시작 | docker start·stop·restart <id> — 그 컨테이너 하나 |
| 묶음 머리의 전체 시작·중지·재시작 | docker compose --project-name <p> start·stop·restart |
범위를 묻지 않습니다. 누르는 자리가 곧 범위입니다. 물어보는 쪽도 검토했지만, compose 위주로 굴리는 서버에서는 거의 모든 클릭에 창이 뜨는데 정작 잦은 것은 컨테이너 하나짜리라, 창을 안 읽고 넘기는 습관만 남습니다.
프로젝트 전체는 다른 서비스도 함께 내렸다 올리므로 대상 목록을 먼저 보여주고 확인을 받습니다 — 그 목록은 이미 화면에 있는 것이라 서버에 아무것도 더 묻지 않습니다.
머리에 적힌 개수는 필터와 무관하게 프로젝트 전체를 셉니다. 버튼이 건드리는 범위와 옆에 적힌 수가 다르면 그 수가 거짓말이 됩니다.
소속은 명령을 하나도 더 쓰지 않고 알아냅니다. docker ps 출력에 이미 Compose가 붙여
둔 라벨이 실려 있습니다. 프로젝트를 알아내려고 파일 시스템을 뒤지거나 docker inspect를
컨테이너마다 부르는 방식이었다면 컨테이너 20개짜리 서버에서 목록 한 번에 왕복 20번이 됐을
겁니다.
compose 파일은 읽지 않습니다. 프로젝트를 이름으로만 부르고, Compose가 실행 중인 컨테이너의 라벨에서 나머지를 복원합니다. 그래서 파일이 이 계정이 못 읽는 곳에 있거나 아예 사라졌어도 동작합니다 — 서버에 배포해 두고 소스는 다른 데 있는 흔한 경우가 여기 해당합니다.
down·up·run은 없습니다. 재시작과 같은 자리에 두기에는 하는 일이 다릅니다.
네트워크 탭 아래에 서버의 sshd 설정을 읽어 짚을 것을 적습니다. PermitRootLogin yes,
PermitEmptyPasswords yes, MaxSessions가 낮은 경우 등입니다.
sshd -T를 쓰지 않습니다. 그쪽이 기본값까지 채운 실효 설정을 주지만 root가 필요하고,
읽기만 하는 화면이 비밀번호부터 요구하면 아무도 열지 않습니다. 대신 이미 열려 있는 SFTP로
설정 파일을 읽습니다 — 어느 배포판에서나 누구나 읽을 수 있게 깔리고, 명령은 하나도 실행하지
않습니다.
그 대가는 이렇습니다. 파일에 적힌 값만 압니다. 파일이 정하지 않은 항목은 sshd
기본값이 적용되는데, 그 값은 배포판마다 다르므로(데비안의 PermitRootLogin은 상류와 다릅니다)
여기서 추측하지 않습니다.
읽을 때 두 가지를 지킵니다. Match 블록 안의 값은 서버 전체 설정이 아닙니다 — Match Address 10.0.0.0/8 아래의 PermitRootLogin yes를 서버 설정으로 보고하는 것이 이 파일을
오독하는 대표적인 방식입니다. 그리고 sshd는 먼저 읽은 값을 씁니다 — 대부분의 설정 형식과
반대이고, 배포판이 Include를 파일 맨 위에 두는 이유입니다.
호스트 편집기의 ProxyJump 칸에 jump@bastion:22를 적으면 그 서버를 먼저 거쳐 갑니다.
경유 서버도 로그인하는 서버이므로 그렇게 다룹니다. 지문을 따로 확인하고 비밀번호도 따로 묻습니다. 경유 서버의 호스트 키를 검사하지 않는 ProxyJump는 그 포트에 응답하는 누구에게든 세션 전체를 넘기는 것이고, 그건 경유가 막으려던 바로 그 일입니다. 목적지의 호스트 키도 그대로 검사합니다 — 경유 서버는 바이트를 전달할 뿐, 반대편이 누구인지 보증하지 않습니다.
한 단계만 지원합니다. 여러 단계를 적으면 첫 단계로 줄이지 않고 거부합니다. 적은 곳이 아닌 데로 접속하는 것이 접속하지 않는 것보다 나쁘기 때문입니다.
경유 서버의 sshd에 AllowTcpForwarding yes가 필요합니다. 꺼져 있으면 sshd가
administratively prohibited로 거절하는데, 그대로 읽으면 계정 권한 문제처럼 보여
엉뚱한 곳을 뒤지게 됩니다. 그래서 어느 서버의 어떤 설정인지 풀어서 보여줍니다.
요약 바에 **CPU 40%**라고 뜨면, 이 탭은 그 40%가 무엇인지 보여줍니다.
- CPU 시간을 사용자·커널·I/O 대기·스틸 시간으로 구분합니다. 90%가 전부 I/O 대기면 CPU가 모자란 게 아니라 디스크를 기다리는 것이고, 전부 스틸 시간이면 바쁘지도 않은데 하이퍼바이저가 CPU 시간을 다른 가상 머신에 할당하는 것입니다. 갈라놓기 전에는 셋 다 '바쁨'입니다
- 코어별 격자. 32코어가 '40%'면 전부 반쯤 바쁜 것이거나 하나가 박히고 나머지가 노는 것인데, 후자가 단일 스레드 병목의 모양입니다
- inode. 용량은 남았는데 파일을 못 만드는 상태고, 그때도 모든 도구가
no space left on device라고 합니다 — 바이트가 떨어졌을 때와 같은 문장입니다 - 네트워크 오류·버림, 디스크 I/O, PSI(사용률이 아니라 '얼마나 기다렸는가'), 실행 대기·I/O 블록, 열린 FD
- NVIDIA 카드가 있으면 사용률·팬·온도·VRAM
보고 있는 동안의 추세를 시간축으로 그리되, 앱이 안 보던 구간은 선을 끊습니다. 없는 기록을 이어 그리지 않습니다.
전부 /proc과 df를 읽습니다. 서버에 설치하는 것은 여전히 없습니다.
화면 속은 데모용 컨테이너입니다(
testdata/demo). GPU는 그 안에서 흉내 낸 값이고, 나머지 숫자는 실제로 그 컨테이너에서 나온 값입니다.
「저 서버 석 달 전에 만졌는데, 내가 뭘 했더라.」
터미널 탭 옆에 접었다 펼 수 있는 패널이 붙습니다. 질문은 늘 두 개입니다 —
어느 폴더에서 일했더라, 그리고 거기서 뭘 쳤더라. 그래서 최근 작업한 폴더가
카드로 쌓이고, 카드마다 거기서 실행한 명령이 최근순으로 들어 있습니다.
「이 위치로 이동」 을 누르면 터미널에 cd가 타이핑됩니다 — 몰래 실행하지
않으니 보고 고치고 취소할 수 있습니다. 「원본」 탭에는 파일이 그대로 있습니다.
원천은 셋이고, 섞지 않고 각각 어디서 왔는지 표시합니다.
| sudo 저널 | 권한을 올려 실행한 것. sudo가 실행 시점의 작업 디렉터리를 기록해 두기 때문에 여기 경로는 추정이 아닙니다 |
| 이 앱의 터미널 | 이 앱에서 친 것. 서버가 아니라 이 컴퓨터에 남으므로 서버의 이력 파일을 건드리지 않습니다 |
| 셸 이력 파일 | ~/.bash_history · ~/.zsh_history. 나머지 대부분이 여기 있습니다 |
이력 파일은 무엇을 쳤는지는 알아도 어디서 쳤는지는 모릅니다. cd를 되짚어
경로를 복원하되, 카드마다 「정확」인지 「추정」인지 적습니다. bash는
HISTTIMEFORMAT을 켜지 않으면 시각을 아예 안 남기므로, 없는 시각을 지어내지
않고 파일이 준 순서만 씁니다.
되짚기에는 함정이 하나 있습니다. bash는 셸이 끝날 때 그 세션의 줄을 파일에
붙이므로, 파일은 세션 여러 개가 이어 붙은 것이고 이음매에는 아무 표시도 없습니다.
한 셸로 취급해 걸으면 새 세션의 cd project가 앞 세션이 끝난 자리에 얹혀
project/project/project 같은, 아무도 서 본 적 없는 경로가 나옵니다. 그래서
상대경로로 도착한 곳이 실제로 있는지 서버에 확인하고, 없으면 홈에서 같은 이동을
시도합니다. 둘 다 아니면 경로를 그대로 두고 해당 경로를 「추정」으로 표시합니다.
셸 이력은 서버별로 켜야 읽습니다 — 기본은 꺼짐입니다. 서버에서 자격증명이 가장 빽빽한 파일이고, 탭을 열 때마다 읽는 기능은 그 사실을 바꿉니다. 비밀번호처럼 보이는 것은 Go 쪽에서 가려서 내보내고 몇 건을 가렸는지 세어 알려줍니다.
/root/.bash_history는 직접 권한을 올렸을 때만 읽습니다.
그 밖에 안 보던 사이를 메우는 것들. 마지막으로 본 이후의 요약, 접속 성공·실패 이력(하루 수천 건이라 목록이 아니라 요약입니다), 보안 업데이트와 재부팅 필요 여부.
「이 서버, 지금 무엇이 지키고 있나.」
방화벽이 깔려 있느냐가 아니라 무엇을 차단하고 있고, 해당 포트에서 실제 프로세스가 수신 중인지에 답합니다. 열린 포트는 네트워크 탭, 접속 실패는 세션 탭, 보안 업데이트는 모니터링 탭에 흩어져 있었고, 어느 탭도 셋을 합친 말을 못 했습니다.
방화벽 ufw fail2ban 활성 지금 차단 중 3 버린 패킷 11,316
nftables 사용 중 jail: sshd 누적 10회 마지막으로 본 뒤 +1,042
「버린 패킷」이 이 화면의 값어치입니다. 나머지가 「그렇게 설정돼 있다」고 말할 때 그 칸만 **「그게 돌아가고 있다」**고 말합니다. 누적이 아니라 마지막으로 본 뒤의 증가로 적습니다 — 총합은 한때 동작했다는 뜻이고, 그건 지금 꺼진 규칙도 할 수 있는 말입니다.
유닛 상태만 보면 안 됩니다. 실측한 서버에서 ufw.service는 enabled·active인데
/etc/ufw/ufw.conf는 ENABLED=no 였습니다 — 유닛은 떠 있고 방화벽은 꺼져 있었습니다.
반대 함정도 있습니다. nftables.service는 부팅 때 한 번 돌고 끝나는 유닛이라 우분투는
아예 비활성으로 출고하고, 그걸 「방화벽 없음」으로 읽으면 거의 모든 우분투 서버에
빨간불이 켜집니다. 그래서 유닛과 설정 파일과 커널을 다 읽고, 어긋나면 그것을 보여줍니다.
규칙 목록은 ufw 와 firewalld 둘 다 읽습니다. ufw 가 있으면 ufw 를 읽습니다 — 둘 다
깔린 서버라면 사람이 설정한 쪽이 ufw 입니다. 없으면 firewall-cmd --list-all 로 활성
zone 을 읽습니다. RHEL · Rocky · CentOS Stream · Fedora 가 여기 해당합니다. firewalld 는
포트가 아니라 서비스 이름(ssh, http)으로 말하므로 그 줄은 이름 그대로 보여주고,
「듣고 있나」 판정은 하지 않습니다 — 포트를 모르는 채로 「미사용」이라 적는 것은 틀린
말이기 때문입니다.
「없음」은 증거가 받쳐줄 때만 말합니다. 전면부가 꺼져 있어도 커널이 패킷 필터를 쓰고 있으면 「확인 필요」입니다 — 도커도 그렇게 보이고, 그걸 방화벽이라 부르면 반대쪽 실수를 하는 것입니다.
설정 파일의 값과 현재 적용된 값을 비교합니다. apt install이 서비스를 먼저 켜 두기
때문에 나중에 파일을 고쳐도 데몬은 처음 읽은 값으로 계속 돕니다. 실측한 서버에서
설정 파일에는 20회로 지정됐지만 실행 중인 jail에는 5회가 적용돼 있었습니다 — 파일만 읽는 화면은 이것을 영원히
못 잡습니다.
규칙과 차단 목록은 root가 필요해 자물쇠 뒤에 있습니다. 탭 자체는 그냥 열립니다 — 아무것도 보여주기 전에 비밀번호부터 요구하는 화면은 아무도 열지 않습니다. 그 비밀번호는 저장하지 않습니다. 키체인을 읽지도 쓰지도 않고, 연결이 끊기면 잊습니다.
막는 명령은 버튼이 아니라 복사할 텍스트입니다. 방화벽 규칙 하나가 그것을 친 세션을 끊고, 이 앱의 다른 변경과 달리 되돌릴 사본이 없습니다.
노트북에서 등록한 서버를 데스크톱에서도 쓰려면 지금까지는 hosts.json 을 손으로
옮겨야 했습니다. 사이드바 아래 동기화 에서 암호화된 파일 하나로 주고받습니다. 저절로 돌지 않습니다 — 내보내고, 옮기고, 읽는 것은 사람이 합니다.
내보내기 — 패스프레이즈를 정하면 litedeck-2026-09-28.ldbackup 파일이 나옵니다.
저장 위치는 OS 저장 창에서 고릅니다. Google Drive·Dropbox·iCloud 폴더에 두거나,
USB 에 담거나, 자기 메일로 보내면 됩니다. LiteDeck 은 그 파일이 어디 갔는지 모릅니다.
가져오기 — 파일을 고르고 패스프레이즈를 넣으면 무엇이 들어 있는지 먼저 보여 줍니다. 호스트마다 이름·주소와 함께 「새 호스트」·「덮어씀」·「같음」이 붙고, 이 기기가 다른 호스트 키를 기억하고 있으면 그것도 표시됩니다. 적용은 그것을 보고 나서입니다.
들어가는 것은 접속 정보(이름·주소·포트·사용자·ProxyJump·그룹), 키의 지문과 라벨, 신뢰한 호스트 키, 승인 정책입니다.
들어가지 않는 것: 비밀번호 · 키 패스프레이즈 · sudo 비밀번호 · 개인키 · 개인키 경로 ·
MCP 토큰 · Command Log · 창 크기. ~/.ssh/config 에서 가져온 호스트도 제외입니다.
개인키 경로가 빠지는 것은 기기마다 다르기 때문입니다. 새 기기에서 받은 호스트의 키 지문이 그 기기에 없으면 접속할 때 키를 고르게 됩니다.
파일의 승인 정책이 이 기기보다 더 엄격하면 그대로 적용되고, 넓으면 기본적으로 적용되지 않습니다. 가져오기 화면에 무엇이 넓어지는지 이름으로 뜨고, 체크박스를 켜야 함께 들어옵니다. 노트북에서 「8시간 묻지 않기」를 켠 파일을 데스크톱에서 읽었다고 그 서버가 조용히 열리지는 않습니다.
만료 시각은 파일에 담기지 않습니다. 자리를 비우는 동안 묻지 말라는 결정은 그 자리에 있는 사람이 하는 것입니다. 완화를 적용하면 그 기기의 시계로 창이 새로 시작합니다.
호스트 키도 같은 원칙입니다. 그 주소에 아무 키도 없을 때만 자동으로 받고, 다른 키가 이미 있으면 건드리지 않고 두 지문을 나란히 보여 줍니다.
동기화가 아닙니다. 만든 시점의 스냅샷이고, 지난달 백업을 열어도 그 뒤에 추가한 호스트는 지워지지 않습니다. 파일에 무엇이 보이는지와 위협 모델은 보안 문서에 적었습니다.




