운영 환경에서 NixOS 실행
NixOS logo는 Tim Cuthbertson()에 의해 작성되며 CC-BY 4.0에 따라 라이센스가 부여됩니다.
지난 주말에 나는 일부 프로젝트를 이전의 사이트 인프라 시설에서 NixOS를 실행하는 VPS로 옮겼다.뭐가 나더러 이렇게 하라고 했어?나는 몇 가지 원인을 생각했다.
우선, 나는 이미 OpenVZ에서 실행되었는데, 다른 옵션에 비해 성능이 상당히 떨어진다.그것 위에서 실행되는 운영체제는 단지 몇 가지 선택일 뿐이다.Ubuntu 16.04(Xenial)는 사용할 수 있지만 유한한 자원에 있어서는 운영Ghost이든 게이츠비에 이 사이트를 구축하려는 시도든 응당한 시간보다 훨씬 오래 걸린다.
이렇게 하는 또 다른 이유는 내가 사이트를 만들 때 많은 일을 한 것을 기억하지 못하기 때문이다.설치했다고 말해도 될까요?아니.100개의 단어의 컴파일러 매개 변수 집합을 외워서 컴파일링 Certbot 을 지원할 수 있습니까?아니.7.2 버전의 PHP가 nginx with Pagespeed에 도달한 후에 업데이트하는 방법을 알고 있습니까?아니오, 확인해 봐야겠어요.
Debian 또는 CentOS와 같은 다른 운영 체제를 선택할 수 있습니다.하지만 나는 결국 닉슨을 선택했다. 그 이유는 다음과 같다.
수명이 끝나다 약간의 세부 사항
어떤 경우, 나는 나의 Arch Linux 시스템에 Nix를 설치했다.거기서부터 이것은 몇 가지 설정을 함께 놓는 문제이다.구축 스크립트 자체는 Elixir가 지원하는 것입니다. 이것은 제가 다음 작업 안내서에서 Haskell 스크립트를 얻을 수 없기 때문입니다.
VPS는 Amazon EC2 인스턴스로 AMI(Amazon Mechanism Image Image)를 시작하는 데 사용됩니다.
첫 번째 정거장은
server.nix
입니다. 이렇게 지어졌습니다.let
nixos = import <nixpkgs/nixos> {
configuration = import ./configuration.nix;
};
in
nixos.system
configuration.nix
시스템에 설정된 대부분의 구성은 다음과 같습니다.{config, pkgs, ...}:
let
unstable = import <nixos-unstable> {};
in
{
imports = [<nixpkgs/nixos/modules/virtualisation/amazon-image.nix> ./users.nix ./firewall.nix ./webserver.nix];
ec2.hvm = true;
networking.hostName = "mnguyen-nix-demo";
environment.systemPackages = [
unstable.caddy2
pkgs.fish
pkgs.htop
pkgs.mosh
pkgs.vim
];
programs.fish.enable = true;
# sudo without requiring password
security.sudo.wheelNeedsPassword = false;
## Enable BBR module
boot.kernelModules = ["tcp_bbr"];
## Network hardening and performance
boot.kernel.sysctl = {
# Disable magic SysRq key
"kernel.sysrq" = 0;
# Ignore ICMP broadcasts to avoid participating in Smurf attacks
"net.ipv4.icmp_echo_ignore_broadcasts" = 1;
# Ignore bad ICMP errors
"net.ipv4.icmp_ignore_bogus_error_responses" = 1;
# Reverse-path filter for spoof protection
"net.ipv4.conf.default.rp_filter" = 1;
"net.ipv4.conf.all.rp_filter" = 1;
# SYN flood protection
"net.ipv4.tcp_syncookies" = 1;
# Do not accept ICMP redirects (prevent MITM attacks)
"net.ipv4.conf.all.accept_redirects" = 0;
"net.ipv4.conf.default.accept_redirects" = 0;
"net.ipv4.conf.all.secure_redirects" = 0;
"net.ipv4.conf.default.secure_redirects" = 0;
"net.ipv6.conf.all.accept_redirects" = 0;
"net.ipv6.conf.default.accept_redirects" = 0;
# Do not send ICMP redirects (we are not a router)
"net.ipv4.conf.all.send_redirects" = 0;
# Do not accept IP source route packets (we are not a router)
"net.ipv4.conf.all.accept_source_route" = 0;
"net.ipv6.conf.all.accept_source_route" = 0;
# Protect against tcp time-wait assassination hazards
"net.ipv4.tcp_rfc1337" = 1;
# TCP Fast Open (TFO)
"net.ipv4.tcp_fastopen" = 3;
## Bufferbloat mitigations
# Requires >= 4.9 & kernel module
"net.ipv4.tcp_congestion_control" = "bbr";
# Requires >= 4.19
"net.core.default_qdisc" = "cake";
};
# disable passwordless SSH
services.openssh.passwordAuthentication = false;
# Let trusted users upload unsigned packages
nix.trustedUsers = ["@wheel"];
# Clean up packages after a while
nix.gc = {
automatic = true;
dates = "weekly UTC";
};
# Disable reinitialisation of AMI on restart or power cycle
systemd.services.amazon-init.enable = false;
swapDevices = [
{
device = "/swapfile";
priority = 10;
size = 1024;
}
];
systemd.services.fathom = {
description = "Fathom Server";
requires = ["network.target"];
after = ["network.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "simple";
User = "minh";
Restart = "on-failure";
RestartSec = 3;
WorkingDirectory = "/var/lib/fathom";
ExecStart = "/home/minh/bin/fathom --config=/etc/fathom.env server";
};
};
}
imports
EC2를 실행하기 위해 특정한 NixOS 구성을 도입하기 위해 파일 ./users.nix
, ./firewall.nix
, ./webserver.nix
을 분리하기 시작했습니다.포장
configuration.nix
꼭대기 부근에 environment.systemPackages
라는 변수가 있는 것을 볼 수 있다.이것은 내가 설치하고 싶은 모든 다른 소프트웨어 패키지를 보여 준다.이 예에서 나는 표준 환매에서 on their wiki, instructions provided by NixOS,
, fish, 그리고 불안정한 NixOS 지점을 설치했다htop.모스 교환
시스템에 교환이 없기 때문에 변수
swapdevices
는 /swapfile
에서 교환 파일을 만드는 것으로 설정됩니다.크기는 MB 단위로 정의되므로 파일 크기는 1GB입니다.회사 명 방화벽
NixOS에는 포트 22의 SSH에만 개방되는 기존 방화벽 설정이 포함되어 있습니다.그것을 변경하려면
networking.firewall.allowedTCPPorts
을 열 포트 목록으로 설정할 수 있습니다.기본 SSH 포트를 다른 포트로 이동하고 싶습니다
services.openssh.listenAddresses
.마지막으로 내
firewall.nix
파일은 다음과 같습니다.{ config, pkgs, ...}:
{
# SSHD Port reassignment
services.openssh.listenAddresses = [
{ addr = "0.0.0.0"; port = 37586; }
];
# Allowed TCP range
networking.firewall.allowedTCPPorts = [80 443 37586];
# Allow Mosh connections
networking.firewall.allowedUDPPortRanges = [{ from = 60000; to = 60010; }];
}
캐디 Caddy 서버
다음은
webserver.nix
에서 웹 서버를 설정했습니다.{config, pkgs, ...}:
let
unstable = import <nixos-unstable> {};
caddyDir = "/var/lib/caddy";
caddyConfig = pkgs.writeText "Caddyfile"
''{
storage file_system {
root /var/lib/caddy
}
}
mnguyen.io {
root * /srv/www/mnguyen.io
file_server
header / {
X-Content-Type-Options "nosniff"
X-Frame-Options "sameorigin"
Referrer-Policy "no-referrer-when-downgrade"
X-UA-Compatible "IE=edge,chrome=1"
X-XSS-Protection "1; mode=block"
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Content-Security-Policy "default-src 'self'; connect-src https://analytics.mnguyen.io 'self'; font-src 'self' data:; img-src https://analytics.mnguyen.io 'self' data:; script-src https://analytics.mnguyen.io 'self' 'unsafe-inline'; style-src 'unsafe-inline'; worker-src 'self'; prefetch-src 'self'; report-uri https://mnguyen.report-uri.com/r/d/csp/enforce; report-to https://mnguyen.report-uri.com/r/d/csp/enforce"
}
}
www.mnguyen.io {
redir https://mnguyen.io{uri}
}
analytics.mnguyen.io {
reverse_proxy localhost:9000
}
'';
in
{
systemd.services.caddy = {
description = "Caddy web server";
after = ["network-online.target"];
wants = ["network-online.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
User = "caddy";
Group = "caddy";
ExecStart = ''
${unstable.caddy2}/bin/caddy run --config ${caddyConfig} --adapter caddyfile
'';
ExecReload = ''
${unstable.caddy2}/bin/caddy reload --config ${caddyConfig} --adapter caddyfile
'';
TimeoutStopSec = "5s";
LimitNOFILE = 1048576;
LimitNPROC = 512;
PrivateTmp = true;
ProtectSystem = "full";
AmbientCapabilities = "cap_net_bind_service";
};
};
users.users.caddy = {
group = "caddy";
uid = config.ids.uids.caddy;
home = caddyDir;
createHome = true;
extraGroups = ["users"];
};
users.groups.caddy.gid = config.ids.uids.caddy;
}
이렇게 하는 목적은 Caddy2가 사용할 Caddyfile
와 명령을 설정하는 시스템d 서비스를 설정하고 서비스의 기능을 설정하여 낮은 포트 번호(정확히 말하면 1024보다 낮음)에서 실행할 수 있도록 하고 그 아래에서 실행될 전용 caddy
사용자를 설정하는 것이다.사용자
여기서 NixOS의 사용자는 몇 줄 코드로 정의할 수 있습니다.입장 가능
users.nix
:{ config, pkgs, ...}:
{
users.users.minh = {
isNormalUser = true;
extraGroups = ["wheel"];
shell = pkgs.fish;
# password = "my secure password";
# hashedPassword = "$6$qTK.7QsrnONOr$ZsAfPlnEPLtpiO9j1qp/POkDga2LtK1UOD0nrG497CegYEq5e.E6iHf5tDqwfLViBSWEsw8sn5t885p6HyRgS1";
openssh.authorizedKeys.keys = [
"ssh-rsa PUBLICKEYHERE"
];
};
}
로고isNormalUser
는 닉슨이 /home/minh
우리에게 메인 디렉터리를 알려주었다.그리고 이 사용자를 sudo
그룹에 추가해서 wheel
접근을 설정합니다. 셸을 fish로 설정하고 시스템에서 이 사용자에게 접근할 수 있는 SSH 키를 설정합니다. 비밀번호를 명확하게 설정하지 않으면 비밀번호로 로그인할 수 없습니다.만약 내가 정말로 비밀번호를 설정하고 싶다면, 나는 안전하지 않은 옵션
password
을 사용할 수 있다. 이것은 문자열이거나, 좀 더 안전하다. passwordHash
(명령mkpasswd -m sha-512
에서 생성된 해시를 사용한다. 상세한 정보는
Fathom 분석
나는 의 마지막 공공 사용 가능한 버전을 추출하고 시스템 d 서비스 파일을 만들어서 실행했다.커뮤니티 게시판에 소유에 대한 토론이 많기 때문에 운영이 안 될까 봐 걱정입니다passwordHash options page.
고맙게도 Fathom은 이 프로그램 중의 하나가 아니라 다른 일이 없는 상황에서 완벽하게 일한다.이것은 NixOS를 위해 포장된 것이 아니기 때문에 이 시스템에서 가장 적은 NixOS 부분일 수 있다.
NixOS 구축
NixOS 패키지를 구축하여 원격 시스템으로 전송하고 구성 파일을 전환하고 새 설정을 활성화하는 두 가지 명령이 있습니다.
nix-build
: NixOS 패키지 구축nix-copy-closure
: NixOS 패키지를 원격으로 전송nix-env
: 업로드한 패키지로 Nix 구성 파일 설정switch-to-configuration
: 시스템 구성을 새 구성으로 전환server_raw = File.read!("server_address.txt")
server_processed = String.replace(server_raw, "\n", "")
defmodule Build do
def upload_to_system(path, address) do
{path_str, _status} = path
fixed_path_str = String.replace(path_str, "\n", "")
System.cmd("nix-copy-closure", ["--to", "--use-substitutes", address, fixed_path_str])
Build.activate_nix(path_str, address)
end
def activate_nix(path, address) do
profile = "/nix/var/nix/profiles/system"
System.cmd("ssh", ["#{address}", "sudo nix-env --profile #{profile} --set #{path}"])
System.cmd("ssh", ["#{address}", "sudo #{profile}/bin/switch-to-configuration switch"])
end
end
System.cmd("nix-build", ["server.nix", "--no-out-link"])
|> Build.upload_to_system(server_processed)
스크립트를 실행하면 이 모든 명령을 순서대로 실행하고 상기 모든 명령을 실행합니다.내가 주의한 점은 설정 파일에 문제가 생기면 스크립트가 끊어져서 서버가 응답하지 않을 수 있다는 것이다.만약 이런 상황이 발생한다면 원격 실례를 다시 시작해야 할 수도 있습니다.저장소에서 Lite 찾기 끝말
나는 닉슨에 대해 적지 않은 이해를 했지만, 대부분의 일처럼 나도 많은 시행착오를 겪었다.고맙게도 이러한 구성을 사용하면 시스템을 쉽게 재구성할 수 있습니다. 예를 들어 포트를 변경할 때 SSH를 통해 연결할 수 없지만 방화벽도 변경해야 한다는 것을 깨닫지 못했습니다.
만약 네가 닉슨에게 흥미가 있다면, 나는 네가 가서 보라고 격려할 것이다.
바이너리 파일이 작동하도록 표준 Linux 시스템을 패치하거나 다른 방식으로 시뮬레이션합니다. 유용한 링크
설정할 때 찾은 리소스를 자세히 살펴보려면 다음과 같이 하십시오.
유형별: NixOS를 로컬로 구축하는 방법과 다른 설치로 보내는 방법을 이해하는 데 유용합니다.
저자 José Luis Lafuente: 맞춤형 시스템d 서비스를 정의하는 부분이 매우 유용하다는 것을 발견했습니다(단지 Caddy 데이터 디렉터리mine was
home
의 설정에 대한 사용자 설정 알림일 뿐입니다)Reference
이 문제에 관하여(운영 환경에서 NixOS 실행), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/contradicthelaw/running-nixos-in-production-2nj5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)