Move hosts to a dedicated folder
This commit is contained in:
parent
cf27e1ad6a
commit
b08fc5a41e
14 changed files with 310 additions and 207 deletions
35
common.nix
Normal file
35
common.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{ inputs, config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with lib.my;
|
||||
{
|
||||
imports =
|
||||
[ inputs.home-manager.nixosModules.home-manager ];
|
||||
# ++ (mapModulesRec' (toString ./modules) import);
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixFlakes;
|
||||
extraOptions = "experimental-features = nix-command flakes";
|
||||
nixPath = [
|
||||
"nixpkgs=${inputs.nixpkgs-unstable}"
|
||||
];
|
||||
settings = {
|
||||
substituters = [
|
||||
"https://nix-community.cachix.org"
|
||||
"http://cache.banditlair.com"
|
||||
"https://cache.nixos.org/"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||
"cache.banditlair.com:4zk7iDvzKh6VN+LxzKIGcVPKgL5dLeyEt2ydrgx4o8c="
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
};
|
||||
system.configurationRevision = with inputs; mkIf (self ? rev) self.rev;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
];
|
||||
}
|
||||
175
flake.nix
175
flake.nix
|
|
@ -6,179 +6,38 @@
|
|||
nix-doom-emacs.url = "github:nix-community/nix-doom-emacs";
|
||||
};
|
||||
|
||||
outputs = { self, home-manager, nixpkgs, nixpkgs-unstable, nix-doom-emacs }:
|
||||
outputs = inputs @ { self, home-manager, nixpkgs, nixpkgs-unstable, ... }:
|
||||
let
|
||||
inherit (lib.my) mapModules mapModulesRec mapHosts;
|
||||
|
||||
system = "x86_64-linux";
|
||||
commonModuleArgs = { pkgs, ... }: {
|
||||
_module.args.pkgs-unstable = import nixpkgs-unstable {
|
||||
inherit (pkgs.stdenv.targetPlatform) system;
|
||||
overlays = [ (import ./overlay.nix) ];
|
||||
|
||||
mkPkgs = pkgs: extraOverlays: import pkgs {
|
||||
inherit system;
|
||||
config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [
|
||||
"corefonts"
|
||||
"steam"
|
||||
"steam-original"
|
||||
"steam-run"
|
||||
];
|
||||
overlays = extraOverlays ++ (pkgs.lib.attrValues self.overlays);
|
||||
};
|
||||
};
|
||||
pkgs = mkPkgs nixpkgs [ self.overlay ];
|
||||
pkgs-unstable = mkPkgs nixpkgs-unstable [ ];
|
||||
|
||||
lib = nixpkgs.lib.extend
|
||||
(self: super: { my = import ./lib { inherit pkgs inputs; lib = self; }; });
|
||||
in
|
||||
{
|
||||
nixosConfigurations.nixos-desktop = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
specialArgs = { inherit nixpkgs; inherit nixpkgs-unstable; inherit nix-doom-emacs; };
|
||||
modules =
|
||||
[
|
||||
home-manager.nixosModules.home-manager
|
||||
commonModuleArgs
|
||||
./hardware/desktop.nix
|
||||
./profiles/base.nix
|
||||
./users
|
||||
(
|
||||
{
|
||||
networking.hostName = "nixos-desktop";
|
||||
# Allow to externally control MPD
|
||||
networking.firewall.allowedTCPPorts = [ 6600 ];
|
||||
lib = lib.my;
|
||||
|
||||
nix.registry.nixpkgs.flake = nixpkgs;
|
||||
|
||||
system.stateVersion = "19.09";
|
||||
}
|
||||
)
|
||||
];
|
||||
overlay = final: prev: {
|
||||
unstable = pkgs-unstable;
|
||||
};
|
||||
|
||||
nixosConfigurations.froidmpa-laptop = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
specialArgs = { inherit nixpkgs; inherit nixpkgs-unstable; inherit nix-doom-emacs; };
|
||||
modules =
|
||||
[
|
||||
home-manager.nixosModules.home-manager
|
||||
commonModuleArgs
|
||||
./hardware/clevo-nl51ru.nix
|
||||
./profiles/base.nix
|
||||
./users
|
||||
(
|
||||
{
|
||||
networking.hostName = "froidmpa-laptop";
|
||||
overlays = { my = (import ./overlay.nix); };
|
||||
|
||||
nix.registry.nixpkgs.flake = nixpkgs;
|
||||
nixosConfigurations = mapHosts ./hosts { };
|
||||
|
||||
home-manager.users.froidmpa = { pkgs, config, ... }: {
|
||||
services.network-manager-applet.enable = true;
|
||||
services.blueman-applet.enable = true;
|
||||
services.grobi = {
|
||||
enable = true;
|
||||
executeAfter = [ "${pkgs.systemd}/bin/systemctl --user restart stalonetray" "${pkgs.feh}/bin/feh --bg-fill ~/.wallpaper.png" ];
|
||||
rules = [
|
||||
{
|
||||
name = "External HDMI";
|
||||
outputs_connected = [ "HDMI-1" ];
|
||||
configure_single = "HDMI-1";
|
||||
primary = true;
|
||||
atomic = true;
|
||||
}
|
||||
{
|
||||
name = "Primary";
|
||||
configure_single = "eDP";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "21.05";
|
||||
}
|
||||
)
|
||||
|
||||
];
|
||||
};
|
||||
|
||||
nixosConfigurations.rpi3 = nixpkgs.lib.nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
modules =
|
||||
[
|
||||
(
|
||||
{ pkgs, ... }: {
|
||||
networking.hostName = "rpi3";
|
||||
|
||||
nix.registry.nixpkgs.flake = nixpkgs;
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
boot.kernelParams = [ "cma=256M" ];
|
||||
|
||||
fileSystems."/" =
|
||||
{
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices = [{ device = "/swapfile"; size = 1024; }];
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keyFiles = [
|
||||
./ssh_keys/phfroidmont-desktop.pub
|
||||
./ssh_keys/phfroidmont-laptop.pub
|
||||
];
|
||||
|
||||
services.adguardhome = {
|
||||
enable = true;
|
||||
|
||||
host = "0.0.0.0";
|
||||
port = 80;
|
||||
openFirewall = true;
|
||||
|
||||
mutableSettings = false;
|
||||
|
||||
settings = {
|
||||
auth_attempts = 5;
|
||||
block_auth_min = 15;
|
||||
dns = {
|
||||
bind_host = "0.0.0.0";
|
||||
port = 53;
|
||||
statistics_interval = 90;
|
||||
querylog_enabled = true;
|
||||
querylog_interval = "2160h";
|
||||
upstream_dns = [
|
||||
"tls://doh.mullvad.net"
|
||||
"[/lan/]192.168.1.1"
|
||||
"[//]192.168.1.1"
|
||||
];
|
||||
local_ptr_upstreams = [ "192.168.1.1" ];
|
||||
use_private_ptr_resolvers = true;
|
||||
resolve_clients = true;
|
||||
bootstrap_dns = [ "9.9.9.10" ];
|
||||
rewrites = [
|
||||
{
|
||||
domain = "rpi3";
|
||||
answer = "192.168.1.2";
|
||||
}
|
||||
{
|
||||
domain = "rpi3.lan";
|
||||
answer = "192.168.1.2";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 53 ];
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim
|
||||
htop
|
||||
];
|
||||
|
||||
nix = {
|
||||
nixPath = [
|
||||
"nixpkgs=${nixpkgs}"
|
||||
];
|
||||
};
|
||||
|
||||
system.stateVersion = "22.05";
|
||||
}
|
||||
)
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
32
hosts/froidmpa-laptop/default.nix
Normal file
32
hosts/froidmpa-laptop/default.nix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../profiles/base.nix
|
||||
../../users
|
||||
];
|
||||
|
||||
home-manager.users.froidmpa = { pkgs, config, ... }: {
|
||||
services.network-manager-applet.enable = true;
|
||||
services.blueman-applet.enable = true;
|
||||
services.grobi = {
|
||||
enable = true;
|
||||
executeAfter = [ "${pkgs.systemd}/bin/systemctl --user restart stalonetray" "${pkgs.feh}/bin/feh --bg-fill ~/.wallpaper.png" ];
|
||||
rules = [
|
||||
{
|
||||
name = "External HDMI";
|
||||
outputs_connected = [ "HDMI-1" ];
|
||||
configure_single = "HDMI-1";
|
||||
primary = true;
|
||||
atomic = true;
|
||||
}
|
||||
{
|
||||
name = "Primary";
|
||||
configure_single = "eDP";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "21.05";
|
||||
}
|
||||
13
hosts/nixos-desktop/default.nix
Normal file
13
hosts/nixos-desktop/default.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../profiles/base.nix
|
||||
../../users
|
||||
];
|
||||
|
||||
# Allow to externally control MPD
|
||||
networking.firewall.allowedTCPPorts = [ 6600 ];
|
||||
|
||||
system.stateVersion = "19.09";
|
||||
}
|
||||
71
hosts/rpi3/default.nix
Normal file
71
hosts/rpi3/default.nix
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
{
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
boot.kernelParams = [ "cma=256M" ];
|
||||
|
||||
fileSystems."/" =
|
||||
{
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices = [{ device = "/swapfile"; size = 1024; }];
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keyFiles = [
|
||||
../../ssh_keys/phfroidmont-desktop.pub
|
||||
../../ssh_keys/phfroidmont-laptop.pub
|
||||
];
|
||||
|
||||
services.adguardhome = {
|
||||
enable = true;
|
||||
|
||||
host = "0.0.0.0";
|
||||
port = 80;
|
||||
openFirewall = true;
|
||||
|
||||
mutableSettings = false;
|
||||
|
||||
settings = {
|
||||
auth_attempts = 5;
|
||||
block_auth_min = 15;
|
||||
dns = {
|
||||
bind_host = "0.0.0.0";
|
||||
port = 53;
|
||||
statistics_interval = 90;
|
||||
querylog_enabled = true;
|
||||
querylog_interval = "2160h";
|
||||
upstream_dns = [
|
||||
"tls://doh.mullvad.net"
|
||||
"[/lan/]192.168.1.1"
|
||||
"[//]192.168.1.1"
|
||||
];
|
||||
local_ptr_upstreams = [ "192.168.1.1" ];
|
||||
use_private_ptr_resolvers = true;
|
||||
resolve_clients = true;
|
||||
bootstrap_dns = [ "9.9.9.10" ];
|
||||
rewrites = [
|
||||
{
|
||||
domain = "rpi3";
|
||||
answer = "192.168.1.2";
|
||||
}
|
||||
{
|
||||
domain = "rpi3.lan";
|
||||
answer = "192.168.1.2";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 53 ];
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
htop
|
||||
];
|
||||
|
||||
system.stateVersion = "22.05";
|
||||
}
|
||||
26
lib/attrs.nix
Normal file
26
lib/attrs.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ lib, ... }:
|
||||
|
||||
with builtins;
|
||||
with lib;
|
||||
rec {
|
||||
# attrsToList
|
||||
attrsToList = attrs:
|
||||
mapAttrsToList (name: value: { inherit name value; }) attrs;
|
||||
|
||||
# mapFilterAttrs ::
|
||||
# (name -> value -> bool)
|
||||
# (name -> value -> { name = any; value = any; })
|
||||
# attrs
|
||||
mapFilterAttrs = pred: f: attrs: filterAttrs pred (mapAttrs' f attrs);
|
||||
|
||||
# Generate an attribute set by mapping a function over a list of values.
|
||||
genAttrs' = values: f: listToAttrs (map f values);
|
||||
|
||||
# anyAttrs :: (name -> value -> bool) attrs
|
||||
anyAttrs = pred: attrs:
|
||||
any (attr: pred attr.name attr.value) (attrsToList attrs);
|
||||
|
||||
# countAttrs :: (name -> value -> bool) attrs
|
||||
countAttrs = pred: attrs:
|
||||
count (attr: pred attr.name attr.value) (attrsToList attrs);
|
||||
}
|
||||
18
lib/default.nix
Normal file
18
lib/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ inputs, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) makeExtensible attrValues foldr;
|
||||
inherit (modules) mapModules;
|
||||
|
||||
modules = import ./modules.nix {
|
||||
inherit lib;
|
||||
self.attrs = import ./attrs.nix { inherit lib; self = { }; };
|
||||
};
|
||||
|
||||
mylib = makeExtensible (self:
|
||||
with self; mapModules ./.
|
||||
(file: import file { inherit self lib pkgs inputs; }));
|
||||
in
|
||||
mylib.extend
|
||||
(self: super:
|
||||
foldr (a: b: a // b) { } (attrValues super))
|
||||
54
lib/modules.nix
Normal file
54
lib/modules.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{ self, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) attrValues readDir pathExists concatLists;
|
||||
inherit (lib) id mapAttrsToList filterAttrs hasPrefix hasSuffix nameValuePair removeSuffix;
|
||||
inherit (self.attrs) mapFilterAttrs;
|
||||
in
|
||||
rec {
|
||||
mapModules = dir: fn:
|
||||
mapFilterAttrs
|
||||
(n: v:
|
||||
v != null &&
|
||||
!(hasPrefix "_" n))
|
||||
(n: v:
|
||||
let path = "${toString dir}/${n}"; in
|
||||
if v == "directory" && pathExists "${path}/default.nix"
|
||||
then nameValuePair n (fn path)
|
||||
else if v == "regular" &&
|
||||
n != "default.nix" &&
|
||||
hasSuffix ".nix" n
|
||||
then nameValuePair (removeSuffix ".nix" n) (fn path)
|
||||
else nameValuePair "" null)
|
||||
(readDir dir);
|
||||
|
||||
mapModules' = dir: fn:
|
||||
attrValues (mapModules dir fn);
|
||||
|
||||
mapModulesRec = dir: fn:
|
||||
mapFilterAttrs
|
||||
(n: v:
|
||||
v != null &&
|
||||
!(hasPrefix "_" n))
|
||||
(n: v:
|
||||
let path = "${toString dir}/${n}"; in
|
||||
if v == "directory"
|
||||
then nameValuePair n (mapModulesRec path fn)
|
||||
else if v == "regular" && n != "default.nix" && hasSuffix ".nix" n
|
||||
then nameValuePair (removeSuffix ".nix" n) (fn path)
|
||||
else nameValuePair "" null)
|
||||
(readDir dir);
|
||||
|
||||
mapModulesRec' = dir: fn:
|
||||
let
|
||||
dirs =
|
||||
mapAttrsToList
|
||||
(k: _: "${dir}/${k}")
|
||||
(filterAttrs
|
||||
(n: v: v == "directory" && !(hasPrefix "_" n))
|
||||
(readDir dir));
|
||||
files = attrValues (mapModules dir id);
|
||||
paths = files ++ concatLists (map (d: mapModulesRec' d id) dirs);
|
||||
in
|
||||
map fn paths;
|
||||
}
|
||||
26
lib/nixos.nix
Normal file
26
lib/nixos.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{ inputs, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with lib.my;
|
||||
let sys = "x86_64-linux";
|
||||
in {
|
||||
mkHost = path: attrs @ { system ? sys, ... }:
|
||||
nixosSystem {
|
||||
inherit system;
|
||||
specialArgs = { inherit lib inputs system; };
|
||||
modules = [
|
||||
{
|
||||
nixpkgs.pkgs = pkgs;
|
||||
nix.registry.nixpkgs.flake = inputs.nixpkgs;
|
||||
networking.hostName = mkDefault (removeSuffix ".nix" (baseNameOf path));
|
||||
}
|
||||
(filterAttrs (n: v: !elem n [ "system" ]) attrs)
|
||||
../common.nix
|
||||
(import path)
|
||||
];
|
||||
};
|
||||
|
||||
mapHosts = dir: attrs @ { system ? system, ... }:
|
||||
mapModules dir
|
||||
(hostPath: mkHost hostPath attrs);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{ config, lib, pkgs, pkgs-unstable, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
services.pcscd.enable = true;
|
||||
environment.systemPackages = with pkgs-unstable; [
|
||||
environment.systemPackages = with pkgs.unstable; [
|
||||
eid-mw
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,42 +1,11 @@
|
|||
{ config, lib, pkgs, nixpkgs, pkgs-unstable, nixpkgs-unstable, ... }:
|
||||
{ config, lib, pkgs, nixpkgs, ... }:
|
||||
{
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixUnstable;
|
||||
settings = {
|
||||
extra-sandbox-paths = [
|
||||
"/var/keys/netrc"
|
||||
];
|
||||
substituters = [
|
||||
"http://cache.banditlair.com"
|
||||
"https://cache.nixos.org/"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"cache.banditlair.com:4zk7iDvzKh6VN+LxzKIGcVPKgL5dLeyEt2ydrgx4o8c="
|
||||
];
|
||||
};
|
||||
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
nixPath = [
|
||||
"nixpkgs=${nixpkgs-unstable}"
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs-unstable; [
|
||||
environment.systemPackages = with pkgs.unstable; [
|
||||
wget
|
||||
inetutils
|
||||
openvpn
|
||||
openfortivpn
|
||||
|
||||
man
|
||||
|
||||
dos2unix
|
||||
|
||||
vim
|
||||
git
|
||||
git-lfs
|
||||
zip
|
||||
unzip
|
||||
|
||||
|
|
@ -52,7 +21,7 @@
|
|||
dnsutils
|
||||
];
|
||||
fonts = {
|
||||
fonts = with pkgs-unstable; [
|
||||
fonts = with pkgs.unstable; [
|
||||
corefonts # Microsoft free fonts
|
||||
meslo-lgs-nf
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{ config, lib, pkgs, pkgs-unstable, nix-doom-emacs, ... }:
|
||||
{ inputs, config, lib, pkgs, ... }:
|
||||
{
|
||||
|
||||
environment.pathsToLink = [ "/share/zsh" ];
|
||||
home-manager.users.froidmpa = { pkgs, config, ... }: {
|
||||
home-manager.users.froidmpa = { config, ... }: {
|
||||
|
||||
imports = [
|
||||
./froidmpa/alacritty.nix
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
./froidmpa/htop.nix
|
||||
./froidmpa/zsh.nix
|
||||
./froidmpa/vscode.nix
|
||||
nix-doom-emacs.hmModule
|
||||
inputs.nix-doom-emacs.hmModule
|
||||
];
|
||||
|
||||
xsession = {
|
||||
|
|
@ -255,7 +255,7 @@
|
|||
};
|
||||
};
|
||||
|
||||
packages = with pkgs-unstable; [
|
||||
packages = with pkgs.unstable; [
|
||||
haskellPackages.xmobar
|
||||
i3lock
|
||||
ncmpcpp
|
||||
|
|
@ -317,7 +317,7 @@
|
|||
systemd.user.services.activitywatch = {
|
||||
Unit.Description = "Start ActivityWatch";
|
||||
Service.Type = "simple";
|
||||
Service.ExecStart = "${pkgs-unstable.activitywatch-bin}/bin/aw-server";
|
||||
Service.ExecStart = "${pkgs.unstable.activitywatch-bin}/bin/aw-server";
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
Service.Restart = "on-failure";
|
||||
Service.RestartSec = 5;
|
||||
|
|
@ -325,7 +325,7 @@
|
|||
systemd.user.services.activitywatch-afk = {
|
||||
Unit.Description = "Start ActivityWatch AFK";
|
||||
Service.Type = "simple";
|
||||
Service.ExecStart = "${pkgs-unstable.activitywatch-bin}/bin/aw-watcher-afk";
|
||||
Service.ExecStart = "${pkgs.unstable.activitywatch-bin}/bin/aw-watcher-afk";
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
Service.Restart = "on-failure";
|
||||
Service.RestartSec = 5;
|
||||
|
|
@ -333,7 +333,7 @@
|
|||
systemd.user.services.activitywatch-window = {
|
||||
Unit.Description = "Start ActivityWatch Window";
|
||||
Service.Type = "simple";
|
||||
Service.ExecStart = "${pkgs-unstable.activitywatch-bin}/bin/aw-watcher-window";
|
||||
Service.ExecStart = "${pkgs.unstable.activitywatch-bin}/bin/aw-watcher-window";
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
Service.Restart = "on-failure";
|
||||
Service.RestartSec = 5;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue