From d63c6191128a3cdaa1784083a48547c79b3ab98d Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Wed, 30 Mar 2022 11:39:23 -0400 Subject: Move Nixpert stuff up in tree hierarchy --- Biz/Cloud.nix | 2 +- Biz/Nixpert.md | 124 +++++++++++++++++++------------- Biz/Nixpert.nix | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++ Biz/Nixpert/Chat.md | 123 -------------------------------- Biz/Nixpert/Chat.nix | 191 -------------------------------------------------- Biz/Nixpert/Course.md | 23 ++++++ Biz/Nixpert/Plan.md | 78 +++++++++++++++++++++ 7 files changed, 369 insertions(+), 363 deletions(-) create mode 100644 Biz/Nixpert.nix delete mode 100644 Biz/Nixpert/Chat.md delete mode 100644 Biz/Nixpert/Chat.nix create mode 100644 Biz/Nixpert/Course.md create mode 100644 Biz/Nixpert/Plan.md diff --git a/Biz/Cloud.nix b/Biz/Cloud.nix index f45cd20..2bbae36 100644 --- a/Biz/Cloud.nix +++ b/Biz/Cloud.nix @@ -15,7 +15,7 @@ bild.os { ./Cloud/Web.nix ./Cloud/Znc.nix "${bild.sources.nixos-mailserver}" - ./Nixpert/Chat.nix + ./Nixpert.nix ]; networking.hostName = "simatime"; networking.domain = "simatime.com"; diff --git a/Biz/Nixpert.md b/Biz/Nixpert.md index d97b504..4e6a163 100644 --- a/Biz/Nixpert.md +++ b/Biz/Nixpert.md @@ -1,78 +1,106 @@ --- -title: Nixpert.chat biz plan +title: Nixpert.chat +header-includes: | + + + --- -# Problem +[Nix](https://nixos.org) is a hermetic, deterministic, and declarative build system, package manager, and operating system. It will save you time and money by making sure: -Nix is hard to use, especially hard to get started with. But the benefits are -compounding for companies that do adopt it. +- your development environment is the same as your production environment +- every build you do is definitive and reproducible +- all your dependencies and environment variables are accounted for +- developers never have to compile something twice - just download it from the cache -The major pain point is getting help: devs often can't go to IRC because it's -hard to use or they are prevented from doing so by confidential company -information. +But, you have to use it right. You can't go half-way in. -# Solution +Do you find Nix hard to use? Is the documentation confusing, the language obtuse and difficult? Have you had trouble training new devs? -We create a paid chat service where devs can quickly get answers to -questions. We'll have a hosted chat client that is easy to use, maybe just use -slack or something. +If so, you need this service. -# Key Metrics +I'm offering dedicated Nix support for a limited number of clients. Here's how it works: -- Number of customers -- Questions answered per shift -- Hours of availability (24/7) +- If you have a problem or question with Nix, NixOS, or Nixpkgs, send me a message +- I will respond within an hour during business hours (~9am-9pm EST) +- I'll stay online with you until your problem is resolved +- If we can't solve it via chat, we'll start a video call to work through it -# Unique Value Proposition +To sign up, say hello in the chat box in the corner to get started, or [register][] an account. -## High-Level Concept +# Why buy as a team? -Direct-line support for your infrastructure and build code. Like monadfix.com for Nix stuff. +Get a dedicated help room just for your team. Speed up your Nix development time for everyone. Accellerate your product development by getting the infrastructure questions out of the way. -# Unfair Advantage +- $3000/month +- ∞ Nix language questions +- ∞ NixOS questions +- ∞ Nixpkgs ecosystem questions +- ∞ tooling support +- 10h code review +- + architecture review +- + security review +- + best practices -- first mover +# Why buy as an individual? -# Channels +Is Nix part of your job, but you don't feel 100% comfortable? Get fast dedicated help from an expert. Perform better at your job. Get your Nix questions answered before anyone else and get back to being productive. -- write articles on: - - common solutions - - benefits of nix - - highlight nix tool - - highlight nix function or technique +- $300/month +- ∞ Nix language questions +- ∞ NixOS questions +- ∞ Nixpkgs ecosystem questions +- ∞ tooling support +- 2h code review +- + architecture review +- + security review +- + best practices -# Customer Segments +# About this service -- crypto companies -- ml companies +This is just a private XMPP server, you can register an account [here][register] or use your own. Join the public [nix-lobby][] room to get started. When you sign up for the dedicated, paid support you'll be added to a private chat room that you can use for future help requests. We also have 1-on-1 and encrypted messaging for any sensitive information. -## Early Adopters +# Who runs this? -- startups, nix companies I know? +I'm [Ben Sima](https://bsima.me) and I've been working with Nix for 5+ years. All of my personal infrastructure runs on NixOS: email, IRC, XMPP, hardware, websites including this one. I've contributed open source packages and modules to nixpkgs. In my day job, I've managed a Nix-based build system and infrastructure for 150+ developers, handling dozens of custom packages, hundreds of builds per day, and a private cache of terabytes of Nix packages. I've probably managed the largest Nix deployment in the world besides the public NixOS.org infrastructure. -# Cost Structure +# Why make this service? -- hourly wages for staff -- infrastructure costs - - chat server via prosody - - errbot for common questions? - - jitsi video chat - - hosted chat room via conversejs.org or JSXC - - chat clients (Dino, iOS: Trillian) +My career mission is to make reliable software, and Nix is one of the best tools for that job. But people often complain that Nix is hard to use. So my goal with this project is to make Nix easy to use and understand. First I will help you with your day-to-day problems. Along the way I will work out better ways to explain the concepts, benefits and usage of Nix. Then I will take these lessons back to the Nix manual and tooling to make the product better. So in buying this service your money actually buys twice the value: you get direct suport of your daily problems, and you get indirect support by improving Nix over time. -# Revenue Streams +The business mantra I operate by is "win and help win." By offering this service I will help your organization win by improving your infrastructure and delivering reliable software products, and the Nix community wins by having more dedicated improvements contributed upstream. -- $500 - $1500 monthly subscription for companies -- pair-programming sessions for added $150/hr +# FAQ -# Growth plan +## Do you offer Nix development or training? -## Unicorn Requirements +For special projects I offer Nix development work and training on a contract basis. Message me at [bsima@simatime.com](xmpp://bsima@simatime.com) and we'll see if your project is a good fit. If not, I can recommend other contractors that I trust will get the job done. -### Sales Penetration +## How do I manage my payment and account? -## Support requirements +It's all manual right now. I'll invoice you for payment at the beginning of every month. If you want to cancel, just message me, no hard feelings. Or just don't pay your invoice I guess. -### Tech Infra +If you want your XMPP account deleted, you can usually do that from an XMPP client, or message me directly and I'll do it from the admin console. -### Customer Support +## Do you log our chats? + +Yeah I save the logs for 30 days. If you need them deleted for some reason, message me an I'll delete any logs. If you have sensitive data, use OMEMO or PGP encryption. + +[register]: https://simatime.com/chat +[nix-lobby]: TODO + + diff --git a/Biz/Nixpert.nix b/Biz/Nixpert.nix new file mode 100644 index 0000000..2eae9d6 --- /dev/null +++ b/Biz/Nixpert.nix @@ -0,0 +1,191 @@ +{ config, pkgs, ... }: +# +# xmpp chat service +# +let + salespage = pkgs.runCommand "salespage" {} '' + mkdir -p $out + ${pkgs.pandoc}/bin/pandoc \ + --standalone \ + -f commonmark_x \ + -t html ${./Chat.md} \ + > $out/index.html + ''; + ports = import ../Cloud/Ports.nix; + ssl = { + cert = "/var/lib/acme/simatime.com/fullchain.pem"; + key = "/var/lib/acme/simatime.com/key.pem"; + }; +in { + networking.firewall.allowedTCPPorts = [ + # https://prosody.im/doc/ports + 5000 # file transfer + 5222 # client connections + 5269 # server-to-server + 5280 # http + 5281 # https + 5347 # external components + 5582 # telnet console + ]; + + services.prosody = { + enable = true; + package = pkgs.prosody.override { + withCommunityModules = [ + "conversejs" + ]; + }; + # when i learn how to use security.acme better, and use separate certs, then i + # can fix this group + group = "nginx"; + admins = [ "bsima@simatime.com" ]; + allowRegistration = true; + inherit ssl; + uploadHttp = { + domain = "upload.simatime.com"; + uploadExpireAfter = toString (60*60*24*30); # 30 days, as seconds + }; + modules = { + announce = true; + bosh = true; + groups = true; + motd = true; + register = true; + server_contact_info = true; + vcard = true; + watchregistrations = true; + websocket = true; + welcome = true; + }; + extraConfig = '' + conversejs_options = { + allow_registration = true; + --- authentication = "internal_plain"; + bosh_service_url = "https://simatime.com/http-bind"; + debug = true; + loglevel = "debug"; + -- default_domain = "simatime.com"; + -- domain_placeholder = "simatime.com"; + -- jid = "simatime.com"; + -- keepalive = true; + -- registration_domain = "simatime.com"; + websocket_url = "wss://simatime.com/xmpp-websocket"; + } + + cross_domain_websocket = { "https://simatime.com", "https://anon.simatime.com" } + cross_domain_bosh = false; -- handle this with nginx + consider_bosh_secure = true; + + -- this is a virtualhost that allows anonymous authentication. use this + -- for the sales lobby. the nix module doesn't support 'authentication' + -- so i have to do this here. + VirtualHost "anon.simatime.com" + authentication = "anonymous" + ssl = { + cafile = "/etc/ssl/certs/ca-bundle.crt"; + key = "/var/lib/acme/simatime.com/key.pem"; + certificate = "/var/lib/acme/simatime.com/fullchain.pem"; + }; + ''; + muc = [ + { + domain = "conference.simatime.com"; + maxHistoryMessages = 10000; + name = "Chat Rooms"; + restrictRoomCreation = "admin"; + roomDefaultHistoryLength = 20; + roomDefaultMembersOnly = true; + roomDefaultModerated = true; + roomDefaultPublic = false; + } + ]; + virtualHosts = { + "simatime.com" = { + domain = "simatime.com"; + enabled = true; + inherit ssl; + }; + }; + }; + + services.nginx.virtualHosts."simatime.com".locations."/http-bind" = { + proxyPass = "https://simatime.com:5281/http-bind"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + add_header Access-Control-Allow-Origin "*"; + ''; + }; + + services.nginx.virtualHosts."simatime.com".locations."/" = { + root = "${salespage}"; + extraConfig = '' + add_header Access-Control-Allow-Origin "*"; + ''; + }; + + services.nginx.virtualHosts."simatime.com".locations."/xmpp-websocket" = { + proxyPass = "https://simatime.com:5281/xmpp-websocket"; + extraConfig = '' + proxy_http_version 1.1; + proxy_buffering off; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_read_timeout 86400; + add_header Access-Control-Allow-Origin "*"; + ''; + }; + + services.nginx.virtualHosts."simatime.com".locations."/chat" = { + proxyPass = "https://simatime.com:5281/conversejs"; + extraConfig = '' + add_header Access-Control-Allow-Origin "*"; + ''; + }; + + services.nginx.virtualHosts."anon.simatime.com" = { + useACMEHost = "simatime.com"; + forceSSL = true; + locations = { + "/http-bind" = { + proxyPass = "https://anon.simatime.com:5281/http-bind"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + if ($request_method ~* "(GET|POST)") { + add_header Access-Control-Allow-Origin "*"; + } + if ($request_method = OPTIONS) { + add_header Access-Control-Allow-Origin "*"; + add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD"; + add_header Access-Control-Allow-Headers "Authorization, Origin, X-Requested-With, Content-Type, Accept"; + return 200; + } + ''; + }; + }; + }; + + users.users.nginx.extraGroups = [ "prosody" ]; + + security.acme.certs.${config.networking.domain}.extraDomainNames = [ + "upload.simatime.com" "conference.simatime.com" "simatime.com" "anon.simatime.com" + ]; + + #security.acme.certs.prosody = { + # domain = "${domain}"; + # group = "prosody"; + # dnsProvider = "rfc2136"; + # #credentialsFile = config.secrets.files.dns_creds.path; + # postRun = "systemctl restart prosody"; + # extraDomainNames = [ + # domain + # "upload.${domain}" + # ]; + #}; +} diff --git a/Biz/Nixpert/Chat.md b/Biz/Nixpert/Chat.md deleted file mode 100644 index 2f229af..0000000 --- a/Biz/Nixpert/Chat.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Professional Nix Chat Support -header-includes: | - - - ---- - -[Nix](https://nixos.org) is a hermetic, deterministic, and declarative build system, package manager, and operating system. It will save you time and money by making sure: - -- your development environment is the same as your production environment -- every build you do is definitive and reproducible -- all your dependencies and environment variables are accounted for -- developers never have to compile something twice - just download it from the cache - -But, you have to use it right. You can't go half-way in. - -Do you find Nix hard to use? Is the documentation confusing, the language obtuse and difficult? Have you had trouble training new devs? - -If so, you need this service. - -I'm offering dedicated Nix support for a limited number of clients. Here's how it works: - -- If you have a problem or question with Nix, NixOS, or Nixpkgs, send me a message -- I will respond within an hour during business hours -- I'll stay online with you until your problem is resolved -- If we can't solve it via chat, we'll start a video call to work through it - -To sign up, say hello in the chat box in the corner to get started, or [register][] an account. - - - -# Why buy as a team? - -Get a dedicated help room just for your team. Speed up your Nix development time for everyone. Accellerate your product development by getting the infrastructure questions out of the way. - -- $3000/month -- ∞ Nix language questions -- ∞ NixOS questions -- ∞ Nixpkgs ecosystem questions -- ∞ tooling support -- 10h code review -- + architecture review -- + security review -- + best practices - -# Why buy as an individual? - -Is Nix part of your job, but you don't feel 100% comfortable? Get fast dedicated help from an expert. Perform better at your job. Get your Nix questions answered before anyone else and get back to being productive. - -- $300/month -- ∞ Nix language questions -- ∞ NixOS questions -- ∞ Nixpkgs ecosystem questions -- ∞ tooling support -- 2h code review -u- + architecture review -- + security review -- + best practices - -# About this service - -This is just a private XMPP server, you can register an account [here][register] or use your own. Join the public [nix-lobby][] room to get started. When you sign up for the dedicated, paid support you'll be added to a private chat room that you can use for future help requests. We also have 1-on-1 and encrypted messaging for any sensitive information. - -# Who runs this? - -I'm [Ben Sima](https://bsima.me) and I've been working with Nix for 5+ years. All of my personal infrastructure runs on NixOS: email, IRC, XMPP, hardware, websites including this one. I've contributed open source packages and modules to nixpkgs. In my day job, I've managed a Nix-based build system and infrastructure for 150+ developers, handling dozens of custom packages, hundreds of builds per day, and a private cache of terabytes of Nix packages. I've probably managed the largest Nix deployment in the world besides the public NixOS.org infrastructure. - -# Why make this service? - -My career mission is to make reliable software, and Nix is one of the best tools for that job. But people often complain that Nix is hard to use. So my goal with this project is to make Nix easy to use and understand. First I will help you with your day-to-day problems. Along the way I will work out better ways to explain the concepts, benefits and usage of Nix. Then I will take these lessons back to the Nix manual and tooling to make the product better. So in buying this service your money actually buys twice the value: you get direct suport of your daily problems, and you get indirect support by improving Nix over time. - -The business manta I operate by is "win and help win." By offering this service I will help your organization win by improving your infrastructure and delivering reliable software products, and the Nix community wins by having more dedicated improvements contributed upstream. - - - -[register]: https://simatime.com/chat -[nix-lobby]: TODO - - diff --git a/Biz/Nixpert/Chat.nix b/Biz/Nixpert/Chat.nix deleted file mode 100644 index 2eae9d6..0000000 --- a/Biz/Nixpert/Chat.nix +++ /dev/null @@ -1,191 +0,0 @@ -{ config, pkgs, ... }: -# -# xmpp chat service -# -let - salespage = pkgs.runCommand "salespage" {} '' - mkdir -p $out - ${pkgs.pandoc}/bin/pandoc \ - --standalone \ - -f commonmark_x \ - -t html ${./Chat.md} \ - > $out/index.html - ''; - ports = import ../Cloud/Ports.nix; - ssl = { - cert = "/var/lib/acme/simatime.com/fullchain.pem"; - key = "/var/lib/acme/simatime.com/key.pem"; - }; -in { - networking.firewall.allowedTCPPorts = [ - # https://prosody.im/doc/ports - 5000 # file transfer - 5222 # client connections - 5269 # server-to-server - 5280 # http - 5281 # https - 5347 # external components - 5582 # telnet console - ]; - - services.prosody = { - enable = true; - package = pkgs.prosody.override { - withCommunityModules = [ - "conversejs" - ]; - }; - # when i learn how to use security.acme better, and use separate certs, then i - # can fix this group - group = "nginx"; - admins = [ "bsima@simatime.com" ]; - allowRegistration = true; - inherit ssl; - uploadHttp = { - domain = "upload.simatime.com"; - uploadExpireAfter = toString (60*60*24*30); # 30 days, as seconds - }; - modules = { - announce = true; - bosh = true; - groups = true; - motd = true; - register = true; - server_contact_info = true; - vcard = true; - watchregistrations = true; - websocket = true; - welcome = true; - }; - extraConfig = '' - conversejs_options = { - allow_registration = true; - --- authentication = "internal_plain"; - bosh_service_url = "https://simatime.com/http-bind"; - debug = true; - loglevel = "debug"; - -- default_domain = "simatime.com"; - -- domain_placeholder = "simatime.com"; - -- jid = "simatime.com"; - -- keepalive = true; - -- registration_domain = "simatime.com"; - websocket_url = "wss://simatime.com/xmpp-websocket"; - } - - cross_domain_websocket = { "https://simatime.com", "https://anon.simatime.com" } - cross_domain_bosh = false; -- handle this with nginx - consider_bosh_secure = true; - - -- this is a virtualhost that allows anonymous authentication. use this - -- for the sales lobby. the nix module doesn't support 'authentication' - -- so i have to do this here. - VirtualHost "anon.simatime.com" - authentication = "anonymous" - ssl = { - cafile = "/etc/ssl/certs/ca-bundle.crt"; - key = "/var/lib/acme/simatime.com/key.pem"; - certificate = "/var/lib/acme/simatime.com/fullchain.pem"; - }; - ''; - muc = [ - { - domain = "conference.simatime.com"; - maxHistoryMessages = 10000; - name = "Chat Rooms"; - restrictRoomCreation = "admin"; - roomDefaultHistoryLength = 20; - roomDefaultMembersOnly = true; - roomDefaultModerated = true; - roomDefaultPublic = false; - } - ]; - virtualHosts = { - "simatime.com" = { - domain = "simatime.com"; - enabled = true; - inherit ssl; - }; - }; - }; - - services.nginx.virtualHosts."simatime.com".locations."/http-bind" = { - proxyPass = "https://simatime.com:5281/http-bind"; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_buffering off; - add_header Access-Control-Allow-Origin "*"; - ''; - }; - - services.nginx.virtualHosts."simatime.com".locations."/" = { - root = "${salespage}"; - extraConfig = '' - add_header Access-Control-Allow-Origin "*"; - ''; - }; - - services.nginx.virtualHosts."simatime.com".locations."/xmpp-websocket" = { - proxyPass = "https://simatime.com:5281/xmpp-websocket"; - extraConfig = '' - proxy_http_version 1.1; - proxy_buffering off; - proxy_set_header Host $host; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_read_timeout 86400; - add_header Access-Control-Allow-Origin "*"; - ''; - }; - - services.nginx.virtualHosts."simatime.com".locations."/chat" = { - proxyPass = "https://simatime.com:5281/conversejs"; - extraConfig = '' - add_header Access-Control-Allow-Origin "*"; - ''; - }; - - services.nginx.virtualHosts."anon.simatime.com" = { - useACMEHost = "simatime.com"; - forceSSL = true; - locations = { - "/http-bind" = { - proxyPass = "https://anon.simatime.com:5281/http-bind"; - extraConfig = '' - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_buffering off; - if ($request_method ~* "(GET|POST)") { - add_header Access-Control-Allow-Origin "*"; - } - if ($request_method = OPTIONS) { - add_header Access-Control-Allow-Origin "*"; - add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD"; - add_header Access-Control-Allow-Headers "Authorization, Origin, X-Requested-With, Content-Type, Accept"; - return 200; - } - ''; - }; - }; - }; - - users.users.nginx.extraGroups = [ "prosody" ]; - - security.acme.certs.${config.networking.domain}.extraDomainNames = [ - "upload.simatime.com" "conference.simatime.com" "simatime.com" "anon.simatime.com" - ]; - - #security.acme.certs.prosody = { - # domain = "${domain}"; - # group = "prosody"; - # dnsProvider = "rfc2136"; - # #credentialsFile = config.secrets.files.dns_creds.path; - # postRun = "systemctl restart prosody"; - # extraDomainNames = [ - # domain - # "upload.${domain}" - # ]; - #}; -} diff --git a/Biz/Nixpert/Course.md b/Biz/Nixpert/Course.md new file mode 100644 index 0000000..3478da3 --- /dev/null +++ b/Biz/Nixpert/Course.md @@ -0,0 +1,23 @@ +--- +title: "Nixpert Course" +--- + +# Nixpert Course +## Accellerate your dev team with cutting edge Nix tooling + +You'll learn how to: + +- create a Nix dev environment +- create a Nix package +- customize your own NixOS image and deployment +- make your first Nixpkgs contribution +- debug Nix code +- quickly navigate a Nix codebase +- scale nix infrastructure + +## Contents + +- Introduction to Nix +- Getting things done +- Shipping confidently with Nix +- Understanding Nix diff --git a/Biz/Nixpert/Plan.md b/Biz/Nixpert/Plan.md new file mode 100644 index 0000000..d97b504 --- /dev/null +++ b/Biz/Nixpert/Plan.md @@ -0,0 +1,78 @@ +--- +title: Nixpert.chat biz plan +--- + +# Problem + +Nix is hard to use, especially hard to get started with. But the benefits are +compounding for companies that do adopt it. + +The major pain point is getting help: devs often can't go to IRC because it's +hard to use or they are prevented from doing so by confidential company +information. + +# Solution + +We create a paid chat service where devs can quickly get answers to +questions. We'll have a hosted chat client that is easy to use, maybe just use +slack or something. + +# Key Metrics + +- Number of customers +- Questions answered per shift +- Hours of availability (24/7) + +# Unique Value Proposition + +## High-Level Concept + +Direct-line support for your infrastructure and build code. Like monadfix.com for Nix stuff. + +# Unfair Advantage + +- first mover + +# Channels + +- write articles on: + - common solutions + - benefits of nix + - highlight nix tool + - highlight nix function or technique + +# Customer Segments + +- crypto companies +- ml companies + +## Early Adopters + +- startups, nix companies I know? + +# Cost Structure + +- hourly wages for staff +- infrastructure costs + - chat server via prosody + - errbot for common questions? + - jitsi video chat + - hosted chat room via conversejs.org or JSXC + - chat clients (Dino, iOS: Trillian) + +# Revenue Streams + +- $500 - $1500 monthly subscription for companies +- pair-programming sessions for added $150/hr + +# Growth plan + +## Unicorn Requirements + +### Sales Penetration + +## Support requirements + +### Tech Infra + +### Customer Support -- cgit v1.2.3