<script setup> import NixCode from "./NixCode.vue" import NixForm from "./NixForm.vue" import { provide, ref } from 'vue' const availableLanguages = { 'en_US.UTF-8': 'English', 'fr_FR.UTF-8': 'Francais' } const availableTimezones = Intl.supportedValuesOf('timeZone') let nixin = { netconf: 'autoconfig', networkingHostname: '', networkingDomain: 'nixin.local', availableBundles: [ { "id": "writeCollectively", "name": "Write collectively : pads", "services": [ 'hedgedoc', 'nextcloud' ] }, { "id": "forge", "name": "Forge : git repo, CI/CD workers, and NixiN", "services": [ 'forgejo', 'forgejorunner', 'nixin' ] }, { "id": "socialMedia", "name": "Social media: hosted social medias in activitypub web-apps", "services": [ 'gotosocial', 'peertube', 'lemmy' ] }], availableServices: [ { "id": "hedgedoc", "name": "Hedgedoc : realtime collaborative markdown editor" }, { "id": "forgejo", "name": "Forgejo : git hosting" }, { "id": "forgejorunner", "name": "Forgejo runner : CD/CI runner for Forgejo" }, { "id": "gotosocial", "name": "Gotosocial : personal light activityPub social media" }, { "id": "peertube", "name": "Peertube : video hosting platform with activityPub" }, { "id": "lemmy", "name": "Lemmy : reddit alternative with activityPub" }, { "id": "nextcloud", "name": "Nextcloud : personnal cloud" }, { "id": "nixin", "name": "NixiN : web ui for configurations" }], bundles: [], services: [], timezone: 'UTC', locale: 'en_US.UTF-8', operatingUser: 'operator', operatingUserPassword: 'CHANGE ME !!!', } nixin.availableServices.forEach((s) => { s.inBundle = [] }) nixin.availableBundles.forEach((b) => { b.services.forEach((s) => { nixin.availableServices.find(item => item.id === s).inBundle.push(b.id); }) }) nixin=ref(nixin) provide('nixin', nixin) function netconfHasBeenChanged(val = '') { if (val === 'autoconfig') { nixin.networkingDomain = 'nixin.local' } else { nixin.networkingDomain = '' } } function selectServices(bundleId, services) { if (nixin.value.bundles.includes(bundleId)) { services.forEach((s) => { if (nixin.value.services.indexOf(s) === -1) { nixin.value.services.push(s) } }) } else { services.forEach((s) => { const index = nixin.value.services.indexOf(s); if (index > -1) { nixin.value.services.splice(index, 1); } }) } } </script> <template> <h2>Networking</h2> <div class="form-cell"> <strong>Choose your network configuration</strong> <div> <label> <input type="radio" v-model="nixin.netconf" value="autoconfig" @click="netconfHasBeenChanged('autoconfig')">I'm a noob in network config, I trust you to provide networking for me (ipv6 only)</label> </div> <div> <label> <input type="radio" v-model="nixin.netconf" value="publicip" @click="netconfHasBeenChanged">My server has a public ip that I can provide </label> </div> <div> <label> <input type="radio" v-model="nixin.netconf" value="localnetwork" @click="netconfHasBeenChanged">My router is set so that my local machine is accessible on the public network </label> </div> <div> <label> <input type="radio" v-model="nixin.netconf" value="wireguard" @click="netconfHasBeenChanged">My server can use a wireguard server i can configure </label> </div> </div> <div class="form-row"> <div class="form-cell"> <label>Machine network name</label> <input required type="text" v-model="nixin.networkingHostname" placeholder="Give your machine a name without spaces, ponctuation or accents" /> </div> </div> <input v-if="nixin.netconf === 'autoconfig'" type="hidden" value="distrilab.fr" /> <div class="form-row" v-if="nixin.netconf !== 'autoconfig'"> <div class="form-cell"> <label>Domain name</label> <input required type="text" v-model="nixin.networkingDomain" placeholder="ex: distrilab.fr" /> </div> </div> <h2>Usage bundles</h2> <div class="form-row"> <div class="form-cell"> <strong>Choose your usage bundles (multiple choices possible if your machine can handle it)</strong> <div v-for="bundle in nixin.availableBundles" :key="bundle"> <label> <input type="checkbox" v-model="nixin.bundles" :id="bundle.id" :value="bundle.id" @change="selectServices(bundle.id, bundle.services)" /> {{ bundle.name }} </label> </div> </div> </div> <h2>Services</h2> <div v-if="nixin.bundles.length === 0">👆 Choose any upper bundle to make associated services appear.</div> <div v-for="service in nixin.availableServices" :key="service"> <div v-if="service.inBundle && service.inBundle.some(ai => nixin.bundles.includes(ai))"> <NixForm :service="service" /> </div> </div> <h2>Other configuration</h2> <div class="form-row"> <div class="form-cell"> <label>Operating UNIX user name</label> <input required type="text" v-model="nixin.operatingUser" /> </div> </div> <div class="form-row"> <div class="form-cell"> <label>Operating UNIX user password</label> <input required type="text" v-model="nixin.operatingUserPassword" /> </div> </div> <div class="form-row"> <div class="form-cell"> <label>Timezone</label> <select v-model="nixin.timezone"> <option v-for="tz in availableTimezones" :selected="nixin.timezone === tz" v-bind:value="tz">{{ tz }}</option> </select> </div> </div> <div class="form-row"> <div class="form-cell"> <label>Locale</label> <select v-model="nixin.locale"> <option v-for="(lang, k) in availableLanguages" :selected="nixin.locale === k" v-bind:value="k">{{ lang }}</option> </select> </div> </div> <h2>Auto-generated configuration.nix file</h2> <pre class="nix-code"> <code> { pkgs, ... }: { networking.hosts = { "127.0.0.1" = [ "{{ nixin.networkingHostname }}.{{nixin.networkingDomain}}" ]; }; networking.hostName = "{{ nixin.networkingHostname }}"; networking.domain = "{{ nixin.networkingDomain }}"; networking.firewall = { allowedTCPPorts = [ 80 443 ]; }; time.timeZone = "{{ nixin.timezone }}"; i18n.defaultLocale = "{{ nixin.locale }}"; <div v-for="(service) in nixin.services" :key="service"> <NixCode :service="service"/> </div> users.users.{{ nixin.operatingUser }} = { isNormalUser = true; extraGroups = [ "wheel" ]; initialPassword = "{{ nixin.operatingUserPassword }}"; }; security.sudo.extraRules= [ { users = [ "{{ nixin.operatingUser }}" ]; commands = [ { command = "ALL" ; options= [ "NOPASSWD" ]; # "SETENV" # Adding the following could be a good idea } ]; } ]; security.acme.defaults.email = "contact@nixin.local"; security.acme.acceptTerms = true; services.nginx = { enable = true; # Use recommended settings recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; # Only allow PFS-enabled ciphers with AES256 sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; virtualHosts."hedgedoc.nixin.local" = { forceSSL = true; enableACME = true; root = "/var/www/hedgedoc"; locations."/".proxyPass = "http://127.0.0.1:8001"; locations."/socket.io/" = { proxyPass = "http://127.0.0.1:8001"; proxyWebsockets = true; extraConfig = "proxy_ssl_server_name on;"; }; }; }; environment.systemPackages = with pkgs; [ git wget tmux mosh htop ]; system.stateVersion = "24.05"; } </code> </pre> </template>