운영 환경에서 NixOS 실행

31983 단어 nixdevops

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와 같은 다른 운영 체제를 선택할 수 있습니다.하지만 나는 결국 닉슨을 선택했다. 그 이유는 다음과 같다.
  • NixOS에 대한 더 많은 정보와 응용 프로그램의 배치와 관리를 어떻게 실행하는지 다른 방법과 비교하고 싶습니다.
  • 저는 시스템 설정을 배치할 수 있는 코드로 성명하는 것에 흥미를 느낍니다. 왜냐하면 저는 매일 패키지 설치와 설정을 실행하는 데 많은 시간을 들여서 이 과정을 더욱 쉽게 합니다. 이것은 틀림없이 저에게 다른 일을 할 시간을 줄 것입니다.
  • 수명이 끝나다 약간의 세부 사항


    어떤 경우, 나는 나의 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 washome의 설정에 대한 사용자 설정 알림일 뿐입니다)
  • 좋은 웹페이지 즐겨찾기