Merge remote-tracking branch 'origin/main'
Some checks failed
/ check (push) Failing after 3m21s

This commit is contained in:
Daniel Flanagan 2024-10-18 10:30:26 -05:00
commit 8278796bb1
7 changed files with 341 additions and 53 deletions

View file

@ -505,6 +505,28 @@
"type": "github"
}
},
"jovian": {
"inputs": {
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1728974938,
"narHash": "sha256-pTPEx6WlM+nJVGrRUGx7Di4ljZMwE9HfvlZ6f3NzNfo=",
"owner": "Jovian-Experiments",
"repo": "Jovian-NixOS",
"rev": "23170582b0658e6afd913149a58863af3a57b376",
"type": "github"
},
"original": {
"owner": "Jovian-Experiments",
"ref": "development",
"repo": "Jovian-NixOS",
"type": "github"
}
},
"libpng": {
"flake": false,
"locked": {
@ -522,6 +544,44 @@
"type": "github"
}
},
"mobile-nixos": {
"flake": false,
"locked": {
"lastModified": 1728423157,
"narHash": "sha256-pJaC+Aef6oixhV6HdWPS2Pq/TgHxEN+MPLYUjighWYI=",
"owner": "lytedev",
"repo": "mobile-nixos",
"rev": "b2c496bbcebc85a28d1d939b56bd331536bd1ac4",
"type": "github"
},
"original": {
"owner": "lytedev",
"repo": "mobile-nixos",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"jovian",
"nixpkgs"
]
},
"locked": {
"lastModified": 1690328911,
"narHash": "sha256-fxtExYk+aGf2YbjeWQ8JY9/n9dwuEt+ma1eUFzF8Jeo=",
"owner": "zhaofengli",
"repo": "nix-github-actions",
"rev": "96df4a39c52f53cb7098b923224d8ce941b64747",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"ref": "matrix-name",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1709479366,
@ -627,6 +687,8 @@
"home-manager": "home-manager",
"home-manager-unstable": "home-manager-unstable",
"hyprland": "hyprland",
"jovian": "jovian",
"mobile-nixos": "mobile-nixos",
"nixpkgs": "nixpkgs_3",
"nixpkgs-unstable": "nixpkgs-unstable",
"slippi": "slippi",

133
flake.nix
View file

@ -31,7 +31,15 @@
slippi.inputs.nixpkgs.follows = "nixpkgs-unstable";
slippi.inputs.home-manager.follows = "home-manager-unstable";
jovian.url = "github:Jovian-Experiments/Jovian-NixOS/development";
jovian.inputs.nixpkgs.follows = "nixpkgs-unstable";
# nnf.url = "github:thelegy/nixos-nftables-firewall?rev=71fc2b79358d0dbacde83c806a0f008ece567b7b";
mobile-nixos = {
url = "github:lytedev/mobile-nixos";
flake = false;
};
};
nixConfig = {
@ -66,6 +74,8 @@
home-manager-unstable,
helix,
hardware,
jovian,
mobile-nixos,
# nnf,
# hyprland,
slippi,
@ -385,6 +395,37 @@
];
};
steamdeck1 = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
home-manager-unstable-defaults
outputs.diskoConfigurations.standard
hardware.nixosModules.common-pc-ssd
common
gaming
graphical-workstation
plasma6
jovian.outputs.nixosModules.jovian
{
networking.hostName = "steamdeck1";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
hardware.bluetooth.enable = true;
networking.networkmanager.enable = true;
home-manager.users.daniel = {
imports = with homeManagerModules; [
firefox-no-tabs
linux-desktop-environment-config
];
};
}
];
};
foxtrot = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux";
modules = with nixosModules; [
@ -401,6 +442,7 @@
virtual-machines-gui
laptop
gaming
cross-compiler
./nixos/foxtrot.nix
@ -432,7 +474,7 @@
# otherwise, they will likely have no effect anyways
text = ''
command -v powerprofilesctl &>/dev/null && bash -x -c 'powerprofilesctl set performance'
command -v swaymsg &>/dev/null && bash -x -c 'swaymsg output eDP-1 mode 2880x1920@60Hz'
command -v swaymsg &>/dev/null && bash -x -c 'swaymsg output eDP-1 mode 2880x1920@120Hz'
'';
})
(writeShellApplication
@ -627,8 +669,95 @@
./nixos/router.nix
];
};
# pinephone-image =
# (import "${mobile-nixos}/lib/eval-with-configuration.nix" {
# configuration = with nixosModules; [
# linux
# home-manager-defaults
# # outputs.diskoConfigurations.unencrypted # can I even disko with an image-based installation?
# common
# wifi
# # TODO: how do I get a minimally useful mobile environment?
# # for me, this means an on-screen keyboard and suspend support I think?
# # I can live in a tty if needed and graphical stuff can all evolve later
# # not worried about modem
# # maybe/hopefully I can pull in or define my own sxmo via nix?
# ];
# device = "pine64-pinephone";
# pkgs = pkgsFor "aarch64-linux";
# })
# .outputs
# .disk-image;
pinephone = let
inherit (nixpkgs-unstable) lib;
in
lib.nixosSystem {
system = "aarch64-linux";
# lib.nixosSystem {
modules = with nixosModules; [
{
imports = [
(import "${mobile-nixos}/lib/configuration.nix" {
device = "pine64-pinephone";
})
];
# nixpkgs.hostPlatform.system = "aarch64-linux";
nixpkgs.buildPlatform = "x86_64-linux";
# TODO: quirk: since the pinephone kernel doesn't seem to have "rpfilter" support, firewall ain't working
networking.firewall.enable = lib.mkForce false;
# TODO: quirk: since git send-email requires perl support, which we don't seem to have on the pinephone, we're just disabling git for now
# TODO: would likely be easier/better to somehow ignore the assertion? probably a way to do that...
programs.git.enable = lib.mkForce false;
# this option is conflicted, presumably due to some assumption in my defaults/common config
# the sd-image module we're importing above has this set to true, so we better go with that?
# that said, I think the mobile-nixos bootloader module has this set to false, so...
# TODO: what does this mean?
boot.loader.generic-extlinux-compatible.enable = lib.mkForce true;
# another conflicting option since I think I default to NetworkManager and this conflicts with networking.wireless.enable
networking.networkmanager.enable = lib.mkForce false;
networking.wireless.enable = lib.mkForce true;
}
# TODO: how do I build this as a .img to flash to an SD card?
# for testing, this seems to work `nixos-rebuild build --impure --flake .#pinephone`
# TODO: would like to use the mobile-nixos installer?
"${nixpkgs-unstable}/nixos/modules/installer/sd-card/sd-image-aarch64-installer.nix"
linux
home-manager-unstable-defaults
# outputs.diskoConfigurations.unencrypted # can I even disko with an image-based installation?
common
wifi
{
system.stateVersion = "24.11";
}
{
# nixpkgs.buildPlatform = "x86_64-linux";
# nixpkgs.hostPlatform = lib.systems.examples.aarch64-multiplatform;
# nixpkgs.localSystem.system = lib.systems.examples.x86_64-linux;
# nixpkgs.crossSystem = lib.mkForce null;
}
];
};
};
images.pinephone = outputs.nixosConfigurations.pinephone.config.system.build.sdImage;
homeConfigurations = {
"deck" = let
system = "x86_64-linux";
@ -657,7 +786,7 @@
};
/*
TODO: nix-on-droid for phone terminal usage?
TODO: nix-on-droid for phone terminal usage? mobile-nixos?
TODO: nix-darwin for work?
TODO: nixos ISO?
*/

View file

@ -327,7 +327,7 @@
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "prohibit-password";
PermitRootLogin = lib.mkForce "prohibit-password";
};
openFirewall = lib.mkDefault true;
@ -370,6 +370,10 @@
};
};
cross-compiler = {config, ...}: {
boot.binfmt.emulatedSystems = ["aarch64-linux" "i686-linux"];
};
default-nix-configuration-and-overlays = {
lib,
config,
@ -392,6 +396,8 @@
trusted-users = ["root" "daniel"];
experimental-features = lib.mkDefault ["nix-command" "flakes"];
extra-platforms = ["i686-linux" "aarch64-linux"];
substituters = [
# TODO: dedupe with flake's config? is that even necessary?
"https://cache.nixos.org/"
@ -1174,43 +1180,43 @@
boot.tmp.cleanOnBoot = true;
services.irqbalance.enable = true;
services.kanidm = {
enableClient = true;
enablePam = true;
package = pkgs.kanidm;
# this is not ready for primetime yet
# services.kanidm = {
# enableClient = true;
# enablePam = true;
# package = pkgs.kanidm;
clientSettings.uri = "https://idm.h.lyte.dev";
unixSettings = {
# hsm_pin_path = "/somewhere/else";
pam_allowed_login_groups = [];
};
};
systemd.tmpfiles.rules = [
"d /etc/kanidm 1755 nobody users -"
];
# clientSettings.uri = "https://idm.h.lyte.dev";
# unixSettings = {
# # hsm_pin_path = "/somewhere/else";
# pam_allowed_login_groups = [];
# };
# };
# systemd.tmpfiles.rules = [
# "d /etc/kanidm 1755 nobody users -"
# ];
# module has the incorrect file permissions out of the box
environment.etc = {
/*
"kanidm" = {
enable = true;
user = "nobody";
group = "users";
mode = "0755";
};
*/
"kanidm/unixd" = {
user = "kanidm-unixd";
group = "kanidm-unixd";
mode = "0700";
};
"kanidm/config" = {
user = "nobody";
group = "users";
mode = "0755";
};
# environment.etc = {
/*
"kanidm" = {
enable = true;
user = "nobody";
group = "users";
mode = "0755";
};
*/
# "kanidm/unixd" = {
# user = "kanidm-unixd";
# group = "kanidm-unixd";
# mode = "0700";
# };
# "kanidm/config" = {
# user = "nobody";
# group = "users";
# mode = "0755";
# };
# };
programs.gnupg.agent = {
enable = true;
@ -1269,7 +1275,6 @@
};
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
system.stateVersion = lib.mkDefault "24.05";
};

View file

@ -220,8 +220,6 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
networking.firewall.allowedUDPPorts = lib.mkIf config.services.headscale.enable [3478];
}
{
# TODO: I think I need to setup my account? wondering if this can be done in nix as well
services.restic.commonPaths = ["/var/lib/soju" "/var/lib/private/soju"];
services.soju = {
enable = true;
@ -1112,26 +1110,27 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
port = 26969;
dir = "/storage/flanilla";
user = "flanilla";
uid = config.users.users.flanilla.uid;
gid = config.users.groups.flanilla.gid;
# uid = config.users.users.flanilla.uid;
# gid = config.users.groups.flanilla.gid;
in {
# flanilla family minecraft server
users.groups.${user} = {};
users.users.${user} = {
isSystemUser = true;
createHome = false;
home = dir;
group = user;
};
virtualisation.oci-containers.containers.minecraft-flanilla = {
autoStart = true;
autoStart = false;
image = "docker.io/itzg/minecraft-server";
user = "${toString uid}:${toString gid}";
# user = "${toString uid}:${toString gid}";
extraOptions = ["--tty" "--interactive"];
environment = {
EULA = "true";
MOTD = "Flanilla Survival! Happy hunting!";
UID = toString uid;
GID = toString gid;
# UID = toString uid;
# GID = toString gid;
STOP_SERVER_ANNOUNCE_DELAY = "20";
TZ = "America/Chicago";
VERSION = "1.21";
@ -1152,6 +1151,10 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
"${dir}/worlds:/worlds"
];
};
systemd.services.podman-minecraft-flanilla.serviceConfig = {
User = user;
Group = user;
};
systemd.tmpfiles.settings = {
"10-${user}-survival" = {
"${dir}/data" = {
@ -1179,26 +1182,27 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
port = 26968;
dir = "/storage/flanilla-creative";
user = "flanilla";
uid = config.users.users.flanilla.uid;
gid = config.users.groups.flanilla.gid;
# uid = config.users.users.flanilla.uid;
# gid = config.users.groups.flanilla.gid;
in {
# flanilla family minecraft server
users.groups.${user} = {};
users.users.${user} = {
isSystemUser = true;
createHome = false;
home = lib.mkForce dir;
group = user;
};
virtualisation.oci-containers.containers.minecraft-flanilla-creative = {
autoStart = true;
image = "docker.io/itzg/minecraft-server";
user = "${toString uid}:${toString gid}";
# user = "${toString uid}:${toString gid}";
extraOptions = ["--tty" "--interactive"];
environment = {
EULA = "true";
MOTD = "Flanilla Creative! Have fun building!";
UID = toString uid;
GID = toString gid;
# UID = toString uid;
# GID = toString gid;
STOP_SERVER_ANNOUNCE_DELAY = "20";
TZ = "America/Chicago";
VERSION = "1.21";
@ -1219,6 +1223,10 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
"${dir}/worlds:/worlds"
];
};
# systemd.services.podman-minecraft-flanilla-creative.serviceConfig = {
# User = user;
# Group = user;
# };
systemd.tmpfiles.settings = {
"10-${user}-creative" = {
"${dir}/data" = {
@ -1783,7 +1791,7 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
virtualisation.oci-containers = {
containers.actual = {
image = "ghcr.io/actualbudget/actual-server:24.10.0";
image = "ghcr.io/actualbudget/actual-server:24.10.1";
autoStart = true;
ports = ["5006:5006"];
volumes = ["/storage/actual:/data"];
@ -1794,6 +1802,29 @@ sudo nix run nixpkgs#ipmitool -- raw 0x30 0x30 0x02 0xff 0x00
extraConfig = ''reverse_proxy :5006'';
};
}
{
services.factorio = {
enable = true;
package = pkgs.factorio-headless.override {
versionsJson = ./factorio-versions.json;
};
admins = ["lytedev"];
autosave-interval = 5;
game-name = "Flanwheel Online";
description = "Space Age 2.0";
openFirewall = true;
lan = true;
# public = true; # NOTE: cannot be true if requireUserVerification is false
port = 34197;
requireUserVerification = false; # critical for DRM-free users
# contains the game password and account password for "public" servers
extraSettingsFile = config.sops.secrets.factorio-server-settings.path;
};
sops.secrets = {
factorio-server-settings = {mode = "0777";};
};
}
];
/*

View file

@ -0,0 +1,58 @@
{
"x86_64-linux": {
"alpha": {
"experimental": {
"name": "factorio_alpha_x64-1.1.110.tar.xz",
"needsAuth": true,
"sha256": "0ndhb94lh47n09a7wshm2inv52fd6rjfa7fk7nk9b7zzh84i7f4x",
"tarDirectory": "x64",
"url": "https://factorio.com/get-download/1.1.110/alpha/linux64",
"version": "1.1.110"
},
"stable": {
"name": "factorio_alpha_x64-1.1.110.tar.xz",
"needsAuth": true,
"sha256": "0ndhb94lh47n09a7wshm2inv52fd6rjfa7fk7nk9b7zzh84i7f4x",
"tarDirectory": "x64",
"url": "https://factorio.com/get-download/1.1.110/alpha/linux64",
"version": "1.1.110"
}
},
"demo": {
"experimental": {
"name": "factorio_demo_x64-1.1.110.tar.xz",
"needsAuth": false,
"sha256": "0dasxgrybl00vrabgrlarsvg0hdg5rvn3y4hsljhqc4zpbf93nxx",
"tarDirectory": "x64",
"url": "https://factorio.com/get-download/1.1.110/demo/linux64",
"version": "1.1.110"
},
"stable": {
"name": "factorio_demo_x64-1.1.110.tar.xz",
"needsAuth": false,
"sha256": "0dasxgrybl00vrabgrlarsvg0hdg5rvn3y4hsljhqc4zpbf93nxx",
"tarDirectory": "x64",
"url": "https://factorio.com/get-download/1.1.110/demo/linux64",
"version": "1.1.110"
}
},
"headless": {
"experimental": {
"name": "factorio_headless_x64-1.1.110.tar.xz",
"needsAuth": false,
"sha256": "0sk4g9y051xjhiwdhj1yz808308zwsbpq3nps1ywvpp56vdycps8",
"tarDirectory": "x64",
"url": "https://factorio.com/get-download/1.1.110/headless/linux64",
"version": "1.1.110"
},
"stable": {
"name": "factorio_headless_x64-1.1.110.tar.xz",
"needsAuth": false,
"sha256": "0sk4g9y051xjhiwdhj1yz808308zwsbpq3nps1ywvpp56vdycps8",
"tarDirectory": "x64",
"url": "https://factorio.com/get-download/1.1.110/headless/linux64",
"version": "1.1.110"
}
}
}
}

View file

@ -214,6 +214,7 @@ in {
udp dport { 80, 443 } accept comment "Allow QUIC to server (see nat prerouting)"
tcp dport { 22 } accept comment "Allow SSH to server (see nat prerouting)"
tcp dport { 25565 } accept comment "Allow Minecraft server connections (see nat prerouting)"
udp dport { 34197 } accept comment "Allow Factorio server connections (see nat prerouting)"
iifname "${lan}" accept comment "Allow local network to access the router"
iifname "tailscale0" accept comment "Allow local network to access the router"
@ -256,6 +257,7 @@ in {
iifname ${wan} tcp dport {26966} dnat to ${hosts.beefcake.ip}
iifname ${wan} tcp dport {25565} dnat to ${hosts.bald.ip}
iifname ${wan} udp dport {25565} dnat to ${hosts.bald.ip}
iifname ${wan} udp dport {34197} dnat to ${hosts.beefcake.ip}
}
chain postrouting {

View file

@ -27,6 +27,7 @@ restic-rascal-passphrase: ENC[AES256_GCM,data:yonKbBh4riGwxc/qcj8F/qrgAtA1sWhYej
restic-rascal-ssh-private-key: ENC[AES256_GCM,data:ddsOs0XsayyQI9qc6LzwQpdDnfwNpbj8PbBJ5fyuqtlVNYndeLxaYcbZI2ULSUhgR1tN0FS+ggGTHQhVvjwksNvpskUGHNKkSLKH3D/mn5N9tsoeAblN4gZsloZdqXBVzEehumcQMdhh6iy6NkNbuinKrVKDhLV25PrFKuSBEYw9VHU7HAMW5Tfop3RzBXjZWETCDAR2OQa7d1dXsJ0Kw6b9RFmRe5MGQ0J7YhjdTg26JGMMVSeHvr5UbiUJkGA5RvOLEDM2Dfai7Lf8yRPZVxUl+rdRsNvNYEoYGu5rGLUFcuqIbQ+s40dP2uXwWauwkIvHUjEahkbP0httj4Kg3qIJBRPg7OuS+MOwAnLEAs3hl5zeBV396yA9qjWW8nhnbml58/uFFbfXbJWTM3r8cMpFbHKD+Ojo/99fm5Vy3pAMzNzEsHOaT+iyDYyNkV5OH1GyKK9n7kIRLdqmWe7GmaKXlwVvNUPi3RvLX9VXq83a4BuupFyTmaNfPGMs/17830aleV674+QVgKh3VyFtuJy6KBpMXDv16wFo,iv:S2I3h6pmKLxEc29E0zn2b8lscqA//5/ZMTV9q+/tdvs=,tag:ALeCT+nrVPDfS21xC555sA==,type:str]
restic-ssh-priv-key-benland: ENC[AES256_GCM,data:G+uiYZTvqXhpJb66j6Q6S+otlXeRX0CdYeMHzSMjIbvbI0AVm0yCU7COO5/O8i47NpvrKKS1kVxVEK8ixLRUowkl3hgRXhxsBIPFnpkMD0ENmJttm4HOpi0qIWMwzPYTjkz/slY4HcTFnCfYy1ZpURQdWwZsr1EdAA05bUMTtM22R3uOMzjO8uf72PCWX7yffo8MxsLmWvNVAOhVlrb2H5KQNR/IquFK3TFoZitq5nVDG9tcEFkX+lgA3zsmCHU/2DvvodgeRoltaAFvgjVznNGf4e5p8owHUtSzX52HwGZRiUlMuhpre2gm1r73n8AyZe41II+LX/85fMfZDdyayIGv3AAMBib8H0/AoChexRcdLQEmzOgRrXsgucDJrWSWP6WMBVyamUm79m5ep0fvL1lJftuJqN0uuq9dBrispdso4x+6jk/pDf5pEM/FE6s1rY832BEb7q0PnjyvVogOez+cIihmMpDdnS0A/8TFzg29i3C+93x5vrt3k7atNzR/jN+/GqX2FKLzxWrrIw2d,iv:IP+N8JQu+XRvwTtBnxu54ujzU5UliltXG3mk9HfJaN8=,tag:4oinE9QMaSh8IfUd/ttM3Q==,type:str]
paperless-superuser-password: ENC[AES256_GCM,data:lypWK73mOYI2hyQAW/4T3cDiVtsts3kKb7LZb9ES3n97Kn5l,iv:jBHUBFbb4GqQ3gnK0h5VCaGj3/kd3/eGa1QFiE7+B9I=,tag:UoQar+x1xVnCV2k+9hYjWA==,type:str]
factorio-server-settings: ENC[AES256_GCM,data:ItK+/eONdAqNAiQxCrCipUmTdIKt274qwVyNnSdOdxxd67XGozs/xr/cCYwwDiUyKQ7mD8oBLL6EVaHbXpObLwGe0Nsnz5jE9GtI0k5184/jsQ==,iv:Qre+BKhdqNDNuOz0PGZJJpTmQxJdNoTbd5FxRy0lrVs=,tag:G4dFdVclUdagyA84Yh653w==,type:str]
sops:
kms: []
gcp_kms: []
@ -51,8 +52,8 @@ sops:
bGpacHFRSkJYUUMwOEh4cVBXZ1NESmsKa5EhZ7148ojCqZldukLcPLr93HqnpNgq
rMI0Nyz4Z4lkTVMRpA94zyNTkNwJ02/CYcKi8EJi6jGZnNPUTcnTwg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-09-13T05:09:18Z"
mac: ENC[AES256_GCM,data:rS12xfQ6FQwVa19rdfk6i1DThUOfsrw+IdKGYOMrX8a7sOKPkNxyxyZASfaKopg3BaM8qmoOFUW4B9VWwTh4d+MhruH3DhJO3UuZpOtDv7H8JFmzqg8rlYx0nm+8/+dB0zjgK7m2FP8wn0jfXraaaQ7/HobgLgGtl+NAsXQkrwQ=,iv:+JO3Yq6Kp2CHu20dSRDOJf0ivq5ASHYrKvlCgg1vGxQ=,tag:y6nIISSZFQwRoFNvqaQWbg==,type:str]
lastmodified: "2024-10-14T14:58:39Z"
mac: ENC[AES256_GCM,data:cNVTWA2S9SMEqoDz7jHuN/9hO20kDyoR03vKw8D72VJiqDEVvAkYeRu6KmGI7DWcfV/2OIrwVjyt+zry92ksYPmF1Xx8s4hu6Z0ooi7mvNrtSMnOLJ68mfpERbdBBcnvX5YivS50mbPhif/kvb5IgUxIQvo2NGFC9Sj7ZnXLa+U=,iv:kKkHVNJ0JE4CRvQdLAfFHKeL4h3o7Z6HJ57HzsqKTJY=,tag:k9K7NS2TZ0uk9u0yd9IAOg==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.0