commit d5e06f3f496b81355aef852401624792f7ff2418 Author: Lucien Cartier-Tilet Date: Sun May 4 02:47:36 2025 +0200 initial commit diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..dc25ec7 --- /dev/null +++ b/.envrc @@ -0,0 +1,10 @@ +if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" +fi + +watch_file flake.nix +watch_file flake.lock +if ! use flake . --no-pure-eval +then + echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2 +fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..00b0e86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*~ +# Devenv +.devenv* +devenv.local.nix + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml +result diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..224b183 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,17 @@ +keys: + - &gampo age1ajemtm502nn2n4q7v4j8meyd5mxtcqngkkedxq2pqzuwu78zp93qnw8q48 + - &gampo-host age197lfdanym647wdaz9uy8hrfqjwj9fs8rm7vs3fsrctceu8mr9gms2jedhz + - &marpa age17pn6suvz2f7zmrm9zxj5hr0putvcvdamqxqt7ewhncgg6ccgmp2qr00xm2 + - &marpa-host age1cnnpnglkvgw5ffv8qpgwpqvj203lh4uwt698y9mxjwklxt8nysmsa8hepn + - &tilo age1g68hxv73llkyc7etzh499ztcrt93pwawy0n8p93px4taqu58mehsp88vjq + - &tilo-host age1awytvphvty4f9wmdn86xnjg9kgetqjx8qlwj5d2882t4fyyzy58s3vg5k4 +creation_rules: + - path_regex: secrets/secrets.yaml$ + key_groups: + - age: + - *gampo + - *gampo-host + - *marpa + - *marpa-host + - *tilo + - *tilo-host diff --git a/README.org b/README.org new file mode 100644 index 0000000..137d833 --- /dev/null +++ b/README.org @@ -0,0 +1,37 @@ +#+title: NixOS Configuration +#+author: Lucien Cartier-Tilet + +This repository contains the NixOS configuration for my personal +setup. It uses Nix Flakes to manache the configuration, making it +reproducible and easy to share across my different machines. + +* Repository Structure +- =flake.nix= :: The main entry point for the Nix Flake. It defines my + NixOS configurations as well as a dev shell which installs the tools + needed for testing and building my configurations. +- =hosts/= :: Directory containing host-specific configurations. Each + host has its own directory with at least a =configuration.nix= file. +- =modules/= :: Custom NixOS modules that can be reused across different + hosts. +- =programs/= :: Programs shared across hosts at the system level that + are not made into configurable modules. +- =secrets/= :: Contains secret values that I cannot or will not share + publicly. +- =system/= :: Common system-level configuration shared across hosts + that are not made into configurable modules. +- =users/phundrak/= :: My home-manager configuration, containing + user-specific settings and applications. +- =users/modules/= :: Custom user NixOS modules that can be reused + across different users. +- =user/scripts/= :: Custom shell scripts shared across users. + +* Updating and Rebuilding the Configuration +In this repository, there are two helper scripts: +- =update.sh= :: Updates the Flake’s lockfile. +- =rebuild.sh= :: Rebuilds the configuration and switch to it + immediately. + +* Contributing +Feel free to fork this repository and make your own changes. If you +have any improvements or suggestions, please open an issue or submit a +pull request. diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ec35bfb --- /dev/null +++ b/flake.lock @@ -0,0 +1,323 @@ +{ + "nodes": { + "cachix": { + "inputs": { + "devenv": [ + "devenv" + ], + "flake-compat": [ + "devenv" + ], + "git-hooks": [ + "devenv" + ], + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1742042642, + "narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=", + "owner": "cachix", + "repo": "cachix", + "rev": "a624d3eaf4b1d225f918de8543ed739f2f574203", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "latest", + "repo": "cachix", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix", + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", + "nix": "nix", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1746189866, + "narHash": "sha256-3sTvuSVBFcXbqg26Qcw/ENJ1s36jtzEcZ0mHqLqvWRA=", + "owner": "cachix", + "repo": "devenv", + "rev": "5fc592d45dd056035e0fd5000893a21609c35526", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742649964, + "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1746204974, + "narHash": "sha256-Evu4H0/kzaQoCNLGQTp+JGTqkywzPx0IAo20Ci2zNck=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "1e8c62c651242fc685b10efc4a48ab777635fb7f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "libgit2": { + "flake": false, + "locked": { + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" + ], + "pre-commit-hooks": [ + "devenv" + ] + }, + "locked": { + "lastModified": 1745930071, + "narHash": "sha256-bYyjarS3qSNqxfgc89IoVz8cAFDkF9yPE63EJr+h50s=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b455edf3505f1bf0172b39a735caef94687d0d9c", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1733212471, + "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1733477122, + "narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1746141548, + "narHash": "sha256-IgBWhX7A2oJmZFIrpRuMnw5RAufVnfvOgHWgIdds+hc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "f02fddb8acef29a8b32f10a335d44828d7825b78", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "home-manager": "home-manager", + "nixpkgs": "nixpkgs_4", + "sops-nix": "sops-nix", + "zen-browser": "zen-browser" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745310711, + "narHash": "sha256-ePyTpKEJTgX0gvgNQWd7tQYQ3glIkbqcW778RpHlqgA=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "5e3e92b16d6fdf9923425a8d4df7496b2434f39c", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "zen-browser": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1745121923, + "narHash": "sha256-8X9JuDfxAEQlBhB0ARgFj9fbDOlCvPx6AbQ1h2T47/g=", + "owner": "youwen5", + "repo": "zen-browser-flake", + "rev": "02084a38e9dbc4fa17f3474c3e9d43bb7db55799", + "type": "github" + }, + "original": { + "owner": "youwen5", + "repo": "zen-browser-flake", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..51ee3bf --- /dev/null +++ b/flake.nix @@ -0,0 +1,125 @@ +{ + description = "Home Manager configuration of phundrak"; + + inputs = { + # Specify the source of Home Manager and Nixpkgs. + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + devenv.url = "github:cachix/devenv"; + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + zen-browser = { + url = "github:youwen5/zen-browser-flake"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + nixConfig = { + extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="; + extra-substituters = "https://devenv.cachix.org"; + }; + + outputs = { + self, + nixpkgs, + home-manager, + devenv, + ... + } @ inputs: let + inherit (self) outputs; + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + in { + formatter.${system} = pkgs.alejandra; + + packages.${system} = { + devenv-up = self.devShells.${system}.default.config.procfileScript; + devenv-test = self.devShells.${system}.default.config.test; + }; + + devShells.${system}.default = devenv.lib.mkShell { + inherit inputs pkgs; + modules = [ + ( + {pkgs, ...}: { + packages = [pkgs.nh]; + git-hooks.hooks = { + alejandra.enable = true; + commitizen.enable = true; + detect-private-keys.enable = true; + end-of-file-fixer.enable = true; + deadnix.enable = true; + ripsecrets.enable = true; + statix.enable = true; + }; + } + ) + ]; + }; + + homeConfigurations = { + "phundrak@marpa" = home-manager.lib.homeManagerConfiguration { + pkgs = nixpkgs.legacyPackages.x86_64-linux; + extraSpecialArgs = { + inherit inputs outputs; + home-conf = "fullHome"; + }; + modules = [ + ./users/phundrak/marpa.nix + inputs.sops-nix.homeManagerModules.sops + ]; + }; + "phundrak@gampo" = home-manager.lib.homeManagerConfiguration { + pkgs = nixpkgs.legacyPackages.x86_64-linux; + extraSpecialArgs = { + inherit inputs outputs; + home-conf = "fullHome"; + }; + modules = [ + ./users/phundrak/gampo.nix + inputs.sops-nix.homeManagerModules.sops + ]; + }; + "phundrak@tilo" = home-manager.lib.homeManagerConfiguration { + pkgs = nixpkgs.legacyPackages.x86_64-linux; + extraSpecialArgs = { + inherit inputs outputs; + home-conf = "minimal"; + }; + modules = [ + ./users/phundrak/tilo.nix + inputs.sops-nix.homeManagerModules.sops + ]; + }; + }; + + nixosConfigurations = { + gampo = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs outputs;}; + modules = [ + ./hosts/gampo/configuration.nix + inputs.sops-nix.nixosModules.sops + ]; + }; + marpa = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs outputs;}; + modules = [ + ./hosts/marpa/configuration.nix + inputs.sops-nix.nixosModules.sops + ]; + }; + tilo = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs outputs;}; + modules = [ + ./hosts/tilo/configuration.nix + inputs.sops-nix.nixosModules.sops + ]; + }; + }; + }; +} diff --git a/hosts/gampo/configuration.nix b/hosts/gampo/configuration.nix new file mode 100644 index 0000000..0dac171 --- /dev/null +++ b/hosts/gampo/configuration.nix @@ -0,0 +1,63 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). +{ + config, + pkgs, + inputs, + ... +}: { + imports = [ + inputs.sops-nix.nixosModules.sops + ./system/hardware-configuration.nix + ./services.nix + ../../modules/system.nix + ../../modules/sops.nix + ../../modules/opentablet.nix + ../../programs/steam.nix + ]; + + sops.secrets.extraHosts = { + inherit (config.users.users.root) group; + owner = config.users.users.phundrak.name; + mode = "0440"; + }; + + boot.initrd.kernelModules = ["i915"]; + + system = { + boot.plymouth.enable = true; + docker = { + enable = true; + autoprune.enable = true; + podman.enable = true; + }; + networking = { + hostname = "gampo"; + id = "0630b33f"; + hostFiles = [config.sops.secrets.extraHosts.path]; + }; + sound.enable = true; + }; + + security.rtkit.enable = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + curl + openssl + wget + ]; + + nix.settings.trusted-users = ["root" "phundrak"]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database + # versions on your system were taken. It‘s perfectly fine and + # recommended to leave this value at the release version of the + # first install of this system. Before changing this value read + # the documentation for this option (e.g. man configuration.nix or + # on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? +} diff --git a/hosts/gampo/services.nix b/hosts/gampo/services.nix new file mode 100644 index 0000000..a7b87fa --- /dev/null +++ b/hosts/gampo/services.nix @@ -0,0 +1,15 @@ +{ + imports = [ + ./services/gnome.nix + ]; + + services = { + # Enable CUPS to print documents. + printing.enable = true; + openssh.enable = true; + fwupd.enable = true; + udev.extraRules = '' + ATTRS{name}=="*TPPS/2 IBM TrackPoint", ENV{ID_INPUT}="", ENV{ID_INPUT_MOUSE}="", ENV{ID_INPUT_POINTINGSTICK}="" + ''; + }; +} diff --git a/hosts/gampo/services/gnome.nix b/hosts/gampo/services/gnome.nix new file mode 100644 index 0000000..fc8177b --- /dev/null +++ b/hosts/gampo/services/gnome.nix @@ -0,0 +1,11 @@ +{ + services.xserver = { + enable = true; + displayManager.gdm.enable = true; + desktopManager.gnome.enable = true; + xkb = { + layout = "fr"; + variant = "bepo"; + }; + }; +} diff --git a/hosts/gampo/system/hardware-configuration.nix b/hosts/gampo/system/hardware-configuration.nix new file mode 100644 index 0000000..a90d01c --- /dev/null +++ b/hosts/gampo/system/hardware-configuration.nix @@ -0,0 +1,46 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot = { + initrd.availableKernelModules = ["ehci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci"]; + initrd.kernelModules = []; + kernelModules = ["kvm-intel"]; + extraModulePackages = []; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/1a8adc62-a11c-4d80-a000-9d37a4fce7b7"; + fsType = "ext4"; + }; + + "/boot" = { + device = "/dev/disk/by-uuid/4032-0CCF"; + fsType = "vfat"; + }; + }; + + swapDevices = [{device = "/dev/disk/by-uuid/85b7722a-4859-4fe6-b838-660314443638";}]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp0s25.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wwp0s29u1u4.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/marpa/configuration.nix b/hosts/marpa/configuration.nix new file mode 100644 index 0000000..0bb79ec --- /dev/null +++ b/hosts/marpa/configuration.nix @@ -0,0 +1,78 @@ +{ + config, + pkgs, + inputs, + ... +}: { + imports = [ + inputs.sops-nix.nixosModules.sops + ./system/hardware-configuration.nix + ./services.nix + ../../modules/system.nix + ../../modules/sops.nix + ../../modules/opentablet.nix + ../../programs/flatpak.nix + ../../programs/steam.nix + ]; + + sops.secrets.extraHosts = { + inherit (config.users.users.root) group; + owner = config.users.users.phundrak.name; + mode = "0440"; + }; + + security.polkit.enable = true; + + fileSystems."/games" = { + device = "/dev/disk/by-uuid/77d32db8-2e85-4593-b6b8-55d4f9d14e1a"; + fsType = "ext4"; + }; + + system = { + amdgpu.enable = true; + boot.plymouth.enable = true; + docker = { + enable = true; + podman.enable = true; + autoprune.enable = true; + }; + networking = { + hostname = "marpa"; + id = "7EA4A111"; + hostFiles = [config.sops.secrets.extraHosts.path]; + firewall.openPortRanges = [ + { + # Sunshine + from = 1714; + to = 1764; + } + ]; + }; + sound = { + enable = true; + jack = true; + }; + }; + + security.rtkit.enable = true; + + nix.settings.trusted-users = ["root" "phundrak"]; + nixpkgs.config.allowUnfree = true; + + environment.systemPackages = with pkgs; [ + clinfo # AMD + curl + openssl + wget + ]; + + programs.nix-ld.enable = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? +} diff --git a/hosts/marpa/services.nix b/hosts/marpa/services.nix new file mode 100644 index 0000000..a74acfa --- /dev/null +++ b/hosts/marpa/services.nix @@ -0,0 +1,23 @@ +{ + imports = [ + ../../modules/ssh.nix + ../../modules/sunshine.nix + ../../modules/xserver.nix + ]; + + modules = { + xserver = { + amdgpu.enable = true; + de = "gnome"; + }; + sunshine = { + enable = true; + autostart = true; + }; + }; + services = { + printing.enable = true; + openssh.enable = true; + fwupd.enable = true; + }; +} diff --git a/hosts/marpa/services/gnome.nix b/hosts/marpa/services/gnome.nix new file mode 100644 index 0000000..0e4d129 --- /dev/null +++ b/hosts/marpa/services/gnome.nix @@ -0,0 +1,11 @@ +{ + services.xserver = { + enable = true; + displayManager.gdm.enable = true; + desktopManager.gnome.enable = true; + xkb = { + layout = "fr"; + variant = "bepo_afnor"; + }; + }; +} diff --git a/hosts/marpa/system/hardware-configuration.nix b/hosts/marpa/system/hardware-configuration.nix new file mode 100644 index 0000000..b8a3613 --- /dev/null +++ b/hosts/marpa/system/hardware-configuration.nix @@ -0,0 +1,50 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot = { + initrd.availableKernelModules = ["nvme" "xhci_pci" "ahci" "thunderbolt" "usb_storage" "usbhid" "sd_mod"]; + initrd.kernelModules = []; + kernelModules = ["kvm-amd"]; + extraModulePackages = []; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/3738e245-f6aa-4ed8-a97b-c7bf199a7810"; + fsType = "ext4"; + }; + + "/boot" = { + device = "/dev/disk/by-uuid/A2C1-2147"; + fsType = "vfat"; + options = ["fmask=0077" "dmask=0077"]; + }; + + "/home" = { + device = "/dev/disk/by-uuid/532f1e53-2cd7-4345-82ec-7309f816cfb8"; + fsType = "btrfs"; + }; + }; + + swapDevices = [{device = "/dev/disk/by-uuid/acdf872f-274c-4316-aeed-11bb1bbde6b8";}]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp17s0u9.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/tilo/configuration.nix b/hosts/tilo/configuration.nix new file mode 100644 index 0000000..6e4a455 --- /dev/null +++ b/hosts/tilo/configuration.nix @@ -0,0 +1,83 @@ +# Edit this configuration file to define what should be installed on your +# system. Help is available in the configuration.nix(5) man page and in +# the NixOS manual (accessible by running ‘nixos-help’). +{ + pkgs, + inputs, + ... +}: { + imports = [ + ./hardware-configuration.nix + inputs.home-manager.nixosModules.default + ../../modules/locale.nix + ../../modules/system.nix + ../../modules/ssh.nix + ../../modules/endlessh.nix + ../../programs/nano.nix + ]; + + system = { + amdgpu.enable = false; + boot = { + kernel = { + hardened = true; + cpuVendor = "amd"; + }; + zfs = { + enable = true; + pools = ["tank"]; + }; + }; + docker.enable = true; + networking = { + hostname = "tilo"; + id = "7110b33f"; + firewall = { + openPorts = [ + 22 # SSH + 80 # HTTP + 443 # HTTPS + 2222 # endlessh + 25565 # Minecraft + ]; + extraCommands = '' + iptables -I INPUT 1 -i 172.16.0.0/12 -p tcp -d 172.17.0.1 -j ACCEPT + iptables -I INPUT 1 -i 172.16.0.0/12 -p tcp -d 172.17.0.1 -j ACCEPT + ''; + }; + }; + nix.gc.automatic = true; + sound.enable = false; + users = { + root.disablePassword = true; + phundrak = true; + }; + console.keyMap = "fr-bepo"; + }; + + modules = { + ssh = { + enable = true; + allowedUsers = ["phundrak"]; + passwordAuthentication = false; + }; + endlessh.enable = true; + }; + + nixpkgs.config.allowUnfree = true; + + environment.systemPackages = [pkgs.openssl]; + + # imports = [ + # # Include the results of the hardware scan. + # ./services.nix + # ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "24.11"; # Did you read the comment? +} diff --git a/hosts/tilo/hardware-configuration.nix b/hosts/tilo/hardware-configuration.nix new file mode 100644 index 0000000..925a6b0 --- /dev/null +++ b/hosts/tilo/hardware-configuration.nix @@ -0,0 +1,45 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot = { + initrd.availableKernelModules = ["xhci_pci" "ahci" "mpt3sas" "usb_storage" "usbhid" "sd_mod"]; + initrd.kernelModules = []; + kernelModules = ["kvm-amd"]; + extraModulePackages = []; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/6f6bb286-3848-482e-b18c-940b459425c8"; + fsType = "ext4"; + }; + + "/boot" = { + device = "/dev/disk/by-uuid/8A5A-5720"; + fsType = "vfat"; + options = ["fmask=0077" "dmask=0077"]; + }; + }; + + swapDevices = [{device = "/dev/disk/by-uuid/a0be51cb-11fa-4087-a14b-c314e35fc34f";}]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp4s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/modules/amdgpu.nix b/modules/amdgpu.nix new file mode 100644 index 0000000..a2a86a2 --- /dev/null +++ b/modules/amdgpu.nix @@ -0,0 +1,17 @@ +{ + pkgs, + lib, + config, + ... +}: +with lib; let + cfg = config.modules.amdgpu; +in { + options.modules.amdgpu.enable = mkEnableOption "Enables an AMD GPU configuration"; + config = mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}" + ]; + hardware.graphics.extraPackages = with pkgs; [rocmPackages.clr.icd]; + }; +} diff --git a/modules/boot.nix b/modules/boot.nix new file mode 100644 index 0000000..9bdc23f --- /dev/null +++ b/modules/boot.nix @@ -0,0 +1,88 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; let + cfg = config.modules.boot; +in { + options.modules.boot = { + amdgpu.enable = mkEnableOption "Enables an AMD GPU configuration"; + kernel = { + package = mkOption { + type = types.raw; + default = pkgs.linuxPackages_zen; + }; + modules = mkOption { + type = types.listOf types.str; + default = []; + }; + cpuVendor = mkOption { + description = "Intel or AMD?"; + type = types.enum ["intel" "amd"]; + default = "amd"; + }; + v4l2loopback = mkOption { + description = "Enables v4l2loopback"; + type = types.bool; + default = true; + }; + hardened = mkEnableOption "Enables hardened Linux kernel"; + }; + zfs = { + enable = mkEnableOption "Enables ZFS"; + pools = mkOption { + type = types.listOf types.str; + default = []; + }; + }; + }; + + config.boot = { + initrd.kernelModules = lists.optional cfg.amdgpu.enable "amdgpu"; + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + supportedFilesystems = mkIf cfg.zfs.enable ["zfs"]; + zfs.extraPools = mkIf cfg.zfs.enable cfg.zfs.pools; + kernelPackages = + if cfg.kernel.hardened + then pkgs.linuxPackages_hardened + else cfg.kernel.package; + kernelModules = + cfg.kernel.modules + ++ ["kvm-${cfg.kernel.cpuVendor}"] + ++ lists.optional cfg.kernel.v4l2loopback "v4l2loopback" + ++ lists.optional cfg.kernel.hardened "tcp_bbr"; + kernel.sysctl = mkIf cfg.kernel.hardened { + "kernel.sysrq" = 0; # Disable magic SysRq key + # 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; + # 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; + # Latency reduction + "net.ipv4.tcp_fastopen" = 3; + # Bufferfloat mitigations + "net.ipv4.tcp_congestion_control" = "bbr"; + "net.core.default_qdisc" = "cake"; + }; + }; +} diff --git a/modules/dev/docker.nix b/modules/dev/docker.nix new file mode 100644 index 0000000..23f42ae --- /dev/null +++ b/modules/dev/docker.nix @@ -0,0 +1,32 @@ +{ + lib, + config, + ... +}: +with lib; let + cfg = config.modules.docker; +in { + options.modules.docker = { + enable = mkEnableOption "Enable Docker"; + podman.enable = mkEnableOption "Enable Podman rather than Docker"; + nvidia.enable = mkEnableOption "Activate Nvidia support"; + autoprune.enable = mkEnableOption "Enable autoprune"; + }; + + config = { + virtualisation = { + docker = mkIf (cfg.enable && !cfg.podman.enable) { + enable = true; + enableNvidia = cfg.nvidia.enable; + autoPrune.enable = cfg.autoprune.enable; + }; + podman = mkIf cfg.podman.enable { + enable = true; + dockerCompat = cfg.enable; + enableNvidia = cfg.nvidia.enable; + dockerSocket.enable = cfg.enable; + autoPrune.enable = cfg.autoprune.enable; + }; + }; + }; +} diff --git a/modules/endlessh.nix b/modules/endlessh.nix new file mode 100644 index 0000000..ceadac6 --- /dev/null +++ b/modules/endlessh.nix @@ -0,0 +1,21 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.endlessh; +in { + options.modules.endlessh = { + enable = mkEnableOption "Enables endlessh."; + port = mkOption { + type = types.port; + default = 2222; + example = 22; + }; + }; + config.services.endlessh-go = mkIf cfg.enable { + inherit (cfg) enable port; + openFirewall = true; + }; +} diff --git a/modules/keys/id_gampo.pub b/modules/keys/id_gampo.pub new file mode 100644 index 0000000..d48d71d --- /dev/null +++ b/modules/keys/id_gampo.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBPhP4p9KGk6jSOxJzBu+RzJPHI6baT0o+xrgPeNRwfq lucien@phundrak.com diff --git a/modules/keys/id_marpa.pub b/modules/keys/id_marpa.pub new file mode 100644 index 0000000..ef6c695 --- /dev/null +++ b/modules/keys/id_marpa.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILw9oiK8tZ5Vpz82RaRLpITU8qeJrT2hjvudGEDQu2QW lucien@phundrak.com diff --git a/modules/keys/id_opn4.pub b/modules/keys/id_opn4.pub new file mode 100644 index 0000000..843213c --- /dev/null +++ b/modules/keys/id_opn4.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFVzXgt8Md+PgOMM3qcBIR/a8uf5s6dnxGbFlG9yD+Gx lucien@phundrak.com diff --git a/modules/keys/id_tilo.pub b/modules/keys/id_tilo.pub new file mode 100644 index 0000000..9c65079 --- /dev/null +++ b/modules/keys/id_tilo.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ7GXp4OfK2j1+7TMjVBL29Ol/6nsEMbfE2wRGkjk3Ya lucien@phundrak.com diff --git a/modules/locale.nix b/modules/locale.nix new file mode 100644 index 0000000..e826217 --- /dev/null +++ b/modules/locale.nix @@ -0,0 +1,16 @@ +{ + i18n = { + defaultLocale = "en_DK.UTF-8"; + extraLocaleSettings = { + LC_ADDRESS = "fr_FR.UTF-8"; + LC_IDENTIFICATION = "fr_FR.UTF-8"; + LC_MEASUREMENT = "fr_FR.UTF-8"; + LC_MONETARY = "fr_FR.UTF-8"; + LC_NAME = "fr_FR.UTF-8"; + LC_NUMERIC = "fr_FR.UTF-8"; + LC_PAPER = "fr_FR.UTF-8"; + LC_TELEPHONE = "fr_FR.UTF-8"; + LC_TIME = "fr_FR.UTF-8"; + }; + }; +} diff --git a/modules/networking.nix b/modules/networking.nix new file mode 100644 index 0000000..0ccaf08 --- /dev/null +++ b/modules/networking.nix @@ -0,0 +1,65 @@ +{ + lib, + config, + ... +}: +with lib; let + cfg = config.modules.networking; +in { + options.modules.networking = { + hostname = mkOption { + type = types.str; + example = "gampo"; + }; + id = mkOption { + type = types.str; + example = "deadb33f"; + }; + hostFiles = mkOption { + type = types.listOf types.path; + example = [/path/to/hostFile]; + default = []; + }; + firewall = { + openPorts = mkOption { + type = types.listOf types.int; + example = [22 80 443]; + default = []; + }; + openPortRanges = mkOption { + type = types.listOf (types.attrsOf types.port); + default = []; + example = [ + { + from = 8080; + to = 8082; + } + ]; + description = '' + A range of TCP and UDP ports on which incoming connections are + accepted. + ''; + }; + extraCommands = mkOption { + type = types.nullOr types.lines; + example = "iptables -A INPUTS -p icmp -j ACCEPT"; + default = null; + }; + }; + }; + + config.networking = { + hostName = cfg.hostname; # Define your hostname. + hostId = cfg.id; + networkmanager.enable = true; + inherit (cfg) hostFiles; + firewall = { + enable = true; + allowedTCPPorts = cfg.firewall.openPorts; + allowedUDPPorts = cfg.firewall.openPorts; + allowedTCPPortRanges = cfg.firewall.openPortRanges; + allowedUDPPortRanges = cfg.firewall.openPortRanges; + extraCommands = (mkIf (cfg.firewall.extraCommands != null)) cfg.firewall.extraCommands; + }; + }; +} diff --git a/modules/nix.nix b/modules/nix.nix new file mode 100644 index 0000000..831e8ee --- /dev/null +++ b/modules/nix.nix @@ -0,0 +1,38 @@ +{ + lib, + config, + ... +}: +with lib; let + cfg = config.modules.nix; +in { + options.modules.nix = { + disableSandbox = mkEnableOption "Disables Nix sandbox"; + gc = { + automatic = mkOption { + type = types.bool; + default = true; + }; + dates = mkOption { + type = types.str; + default = "Monday 01:00 UTC"; + }; + options = mkOption { + type = types.str; + default = "--delete-older-than 30d"; + }; + }; + }; + + config = { + nix = { + settings = { + sandbox = cfg.disableSandbox; + experimental-features = ["nix-command" "flakes"]; + auto-optimise-store = true; + }; + inherit (cfg) gc; + }; + nixpkgs.config.allowUnfree = true; + }; +} diff --git a/modules/opentablet.nix b/modules/opentablet.nix new file mode 100644 index 0000000..d4cae11 --- /dev/null +++ b/modules/opentablet.nix @@ -0,0 +1,6 @@ +{ + hardware.opentabletdriver = { + enable = true; + daemon.enable = true; + }; +} diff --git a/modules/plymouth.nix b/modules/plymouth.nix new file mode 100644 index 0000000..744665d --- /dev/null +++ b/modules/plymouth.nix @@ -0,0 +1,33 @@ +{ + pkgs, + lib, + config, + ... +}: +with lib; let + cfg = config.modules.boot.plymouth; +in { + options.modules.boot.plymouth.enable = mkEnableOption "Enables Plymouth at system boot"; + config.boot = mkIf cfg.enable { + plymouth = { + inherit (cfg) enable; + theme = "circle_hud"; + themePackages = with pkgs; [ + (adi1090x-plymouth-themes.override { + selected_themes = ["circle_hud"]; + }) + ]; + }; + consoleLogLevel = 3; + initrd.verbose = false; + kernelParams = [ + "quiet" + "splash" + "boot.shell_on_fail" + "udev.log_priority=3" + "rd.systemd.show_status=auto" + ]; + # Loader appears only if a key is pressed + loader.timeout = 0; + }; +} diff --git a/modules/sops.nix b/modules/sops.nix new file mode 100644 index 0000000..4f825ab --- /dev/null +++ b/modules/sops.nix @@ -0,0 +1,17 @@ +{ + sops = { + defaultSopsFile = ../secrets/secrets.yaml; + defaultSopsFormat = "yaml"; + age = { + # automatically import user SSH keys as age keys + sshKeyPaths = [ + "/home/phundrak/.ssh/id_ed25519" + "/etc/ssh/ssh_host_ed25519_key" + ]; + # this will use an age key that is expected to already be in the filesystem + keyFile = "/var/lib/sops-nix/key.txt"; + # generate a new key if the key specified above does not exist + generateKey = true; + }; + }; +} diff --git a/modules/sound.nix b/modules/sound.nix new file mode 100644 index 0000000..1d973a7 --- /dev/null +++ b/modules/sound.nix @@ -0,0 +1,40 @@ +{ + lib, + config, + pkgs, + ... +}: +with lib; let + cfg = config.modules.sound; +in { + options.modules.sound = { + enable = mkEnableOption "Whether to enable sounds with Pipewire"; + alsa = mkOption { + type = types.bool; + example = true; + default = true; + description = "Whether to enable ALSA support with Pipewire"; + }; + jack = mkOption { + type = types.bool; + example = true; + default = false; + description = "Whether to enable JACK support with Pipewire"; + }; + package = mkOption { + type = types.package; + example = pkgs.pulseaudio; + default = pkgs.pulseaudioFull; + description = "Which base package to use for PulseAudio"; + }; + }; + + config.services.pipewire = mkIf cfg.enable { + enable = true; + alsa = mkIf cfg.alsa { + enable = mkDefault true; + support32Bit = mkDefault true; + }; + jack.enable = mkDefault cfg.jack; + }; +} diff --git a/modules/ssh.nix b/modules/ssh.nix new file mode 100644 index 0000000..550c863 --- /dev/null +++ b/modules/ssh.nix @@ -0,0 +1,30 @@ +{ + lib, + config, + ... +}: +with lib; let + cfg = config.modules.ssh; +in { + options.modules.ssh = { + enable = mkEnableOption "Enables OpenSSH"; + allowedUsers = mkOption { + type = types.listOf types.str; + example = ["alice" "bob"]; + default = ["phundrak"]; + }; + passwordAuthentication = mkOption { + type = types.bool; + example = true; + default = false; + }; + }; + config.services.openssh = mkIf cfg.enable { + enable = true; + settings = { + AllowUsers = cfg.allowedUsers; + PermitRootLogin = "no"; + PasswordAuthentication = cfg.passwordAuthentication; + }; + }; +} diff --git a/modules/sunshine.nix b/modules/sunshine.nix new file mode 100644 index 0000000..0d7edef --- /dev/null +++ b/modules/sunshine.nix @@ -0,0 +1,22 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.sunshine; +in { + options.modules.sunshine = { + enable = mkEnableOption "Enables moonlight"; + autostart = mkEnableOption "Enables autostart"; + }; + config.services.sunshine = mkIf cfg.enable { + enable = true; + autoStart = cfg.autostart; + capSysAdmin = true; + openFirewall = true; + settings = { + sunshine_name = "marpa"; + }; + }; +} diff --git a/modules/system.nix b/modules/system.nix new file mode 100644 index 0000000..dbf0bf8 --- /dev/null +++ b/modules/system.nix @@ -0,0 +1,171 @@ +{ + pkgs, + lib, + config, + ... +}: +with lib; let + cfg = config.system; +in { + imports = [ + ./amdgpu.nix + ./boot.nix + ./locale.nix + ./networking.nix + ./nix.nix + ./plymouth.nix + ./sound.nix + ./users.nix + ./dev/docker.nix + ]; + + options.system = { + amdgpu.enable = mkEnableOption "Enables AMD GPU support"; + boot = { + kernel = { + package = mkOption { + type = types.raw; + default = pkgs.linuxPackages_zen; + }; + modules = mkOption { + type = types.listOf types.str; + default = []; + }; + cpuVendor = mkOption { + description = "Intel or AMD?"; + type = types.enum ["intel" "amd"]; + default = "amd"; + }; + v4l2loopback = mkOption { + description = "Enables v4l2loopback"; + type = types.bool; + default = true; + }; + hardened = mkEnableOption "Enables hardened Linux kernel"; + }; + plymouth.enable = mkEnableOption "Enables Plymouth"; + zfs = { + enable = mkEnableOption "Enables ZFS"; + pools = mkOption { + type = types.listOf types.str; + default = []; + }; + }; + }; + docker = { + enable = mkEnableOption "Enable Docker"; + podman.enable = mkEnableOption "Enable Podman rather than Docker"; + nvidia.enable = mkEnableOption "Activate Nvidia support"; + autoprune.enable = mkEnableOption "Enable autoprune"; + }; + networking = { + hostname = mkOption { + type = types.str; + example = "gampo"; + }; + id = mkOption { + type = types.str; + example = "deadb33f"; + }; + hostFiles = mkOption { + type = types.listOf types.path; + example = [/path/to/hostFile]; + default = []; + }; + firewall = { + openPorts = mkOption { + type = types.listOf types.int; + example = [22 80 443]; + default = []; + }; + openPortRanges = mkOption { + type = types.listOf (types.attrsOf types.port); + default = []; + example = [ + { + from = 8080; + to = 8082; + } + ]; + description = '' + A range of TCP and UDP ports on which incoming connections are + accepted. + ''; + }; + extraCommands = mkOption { + type = types.nullOr types.lines; + example = "iptables -A INPUTS -p icmp -j ACCEPT"; + default = null; + }; + }; + }; + nix = { + disableSandbox = mkOption { + type = types.bool; + default = false; + }; + gc = { + automatic = mkOption { + type = types.bool; + default = true; + }; + dates = mkOption { + type = types.str; + default = "Monday 01:00 UTC"; + }; + options = mkOption { + type = types.str; + default = "--delete-older-than 30d"; + }; + }; + }; + sound = { + enable = mkEnableOption "Whether to enable sounds with Pipewire"; + alsa = mkOption { + type = types.bool; + example = true; + default = true; + description = "Whether to enable ALSA support with Pipewire"; + }; + jack = mkOption { + type = types.bool; + example = true; + default = false; + description = "Whether to enable JACK support with Pipewire"; + }; + package = mkOption { + type = types.package; + example = pkgs.pulseaudio; + default = pkgs.pulseaudioFull; + description = "Which base package to use for PulseAudio"; + }; + }; + users = { + root.disablePassword = mkEnableOption "Disables root password"; + phundrak = mkOption { + type = types.bool; + default = true; + }; + }; + timezone = mkOption { + type = types.str; + default = "Europe/Paris"; + }; + console.keyMap = mkOption { + type = types.str; + default = "fr"; + }; + }; + + config = { + time.timeZone = cfg.timezone; + console.keyMap = cfg.console.keyMap; + modules = { + boot = { + inherit (cfg) amdgpu; + inherit (cfg.boot) kernel plymouth zfs; + }; + inherit (cfg) sound users networking docker amdgpu; + }; + }; +} diff --git a/modules/users.nix b/modules/users.nix new file mode 100644 index 0000000..aae7394 --- /dev/null +++ b/modules/users.nix @@ -0,0 +1,39 @@ +{ + lib, + config, + pkgs, + ... +}: +with lib; let + cfg = config.modules.users; +in { + options.modules.users = { + root.disablePassword = mkEnableOption "Disables root password"; + phundrak = mkOption { + type = types.bool; + default = true; + }; + }; + + config = { + users.users = { + root = { + hashedPassword = mkIf cfg.root.disablePassword "*"; + shell = pkgs.zsh; + }; + phundrak = { + isNormalUser = true; + description = "Lucien Cartier-Tilet"; + extraGroups = ["networkmanager" "wheel" "docker" "dialout" "podman"]; + shell = pkgs.zsh; + openssh.authorizedKeys.keyFiles = [ + ./keys/id_gampo.pub + ./keys/id_marpa.pub + ./keys/id_tilo.pub + ./keys/id_opn4.pub + ]; + }; + }; + programs.zsh.enable = true; + }; +} diff --git a/modules/xserver.nix b/modules/xserver.nix new file mode 100644 index 0000000..872b60e --- /dev/null +++ b/modules/xserver.nix @@ -0,0 +1,41 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.xserver; +in { + options.modules.xserver = { + amdgpu.enable = mkEnableOption "Enables AMD GPU support"; + de = mkOption { + type = types.enum ["gnome" "kde"]; + default = "gnome"; + example = "kde"; + description = "Which DE to enable"; + }; + }; + config.services = { + displayManager.sddm.enable = mkIf (cfg.de == "kde") true; + desktopManager.plasma6.enable = mkIf (cfg.de == "kde") true; + + gnome = mkIf (cfg.de == "gnome") { + gnome-browser-connector.enable = true; + games.enable = false; + gnome-remote-desktop.enable = true; + gnome-online-accounts.enable = true; + sushi.enable = true; + }; + + xserver = { + enable = true; + displayManager.gdm.enable = mkIf (cfg.de == "gnome") true; + desktopManager.gnome.enable = mkIf (cfg.de == "gnome") true; + videoDrivers = lists.optional cfg.amdgpu.enable "amdgpu"; + xkb = { + layout = "fr"; + variant = "bepo_afnor"; + }; + }; + }; +} diff --git a/programs/flatpak.nix b/programs/flatpak.nix new file mode 100644 index 0000000..1ff0c53 --- /dev/null +++ b/programs/flatpak.nix @@ -0,0 +1,3 @@ +{ + services.flatpak.enable = true; +} diff --git a/programs/hyprland.nix b/programs/hyprland.nix new file mode 100644 index 0000000..3c45fe9 --- /dev/null +++ b/programs/hyprland.nix @@ -0,0 +1,49 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.hyprland; +in { + options.modules.hyprland = { + enable = mkEnableOption "Enables Hyprland"; + config = mkOption { + type = types.lines; + default = ""; + }; + waybar = { + config = mkOption { + type = types.lines; + default = ""; + }; + style = mkOption { + type = types.nullOr types.path; + default = null; + }; + }; + }; + + config = { + wayland.windowManager.hyprland = mkIf cfg.enable { + enable = true; + xwayland.enable = true; + systemd.enable = true; + extraConfig = cfg.config; + }; + services.wpaperd = { + enable = true; + settings = '' + [default] + path = "/home/phundrak/Pictures/Wallpapers/nord" + duration = "5m" + sorting = "ascending" + ''; + }; + programs.waybar = { + enable = true; + inherit (cfg.waybar) config style; + systemd.enableInspect = true; + }; + }; +} diff --git a/programs/kdeconnect.nix b/programs/kdeconnect.nix new file mode 100644 index 0000000..446fbd2 --- /dev/null +++ b/programs/kdeconnect.nix @@ -0,0 +1,15 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.kdeconnect; +in { + options.modules.kdeconnect.enable = mkEnableOption "Enable KDEConnect"; + + config.services.kdeconnect = mkIf cfg.enable { + enable = true; + indicator = true; + }; +} diff --git a/programs/nano.nix b/programs/nano.nix new file mode 100644 index 0000000..0b2a8aa --- /dev/null +++ b/programs/nano.nix @@ -0,0 +1,14 @@ +{ + programs.nano = { + enable = true; + syntaxHighlight = true; + nanorc = '' + set tabsize 2 + set autoindent + set atblanks + set linenumber + set smarthome + set softwrap + ''; + }; +} diff --git a/programs/steam.nix b/programs/steam.nix new file mode 100644 index 0000000..2e54553 --- /dev/null +++ b/programs/steam.nix @@ -0,0 +1,21 @@ +{pkgs, ...}: { + programs = { + steam = { + enable = true; + protontricks.enable = true; + remotePlay.openFirewall = true; + localNetworkGameTransfers.openFirewall = true; + gamescopeSession.enable = true; + extraCompatPackages = [pkgs.proton-ge-bin]; + }; + gamescope = { + enable = true; + capSysNice = true; + args = [ + "--rt" + "--expose-wayland" + ]; + }; + }; + hardware.steam-hardware.enable = true; +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml new file mode 100644 index 0000000..b04f8f8 --- /dev/null +++ b/secrets/secrets.yaml @@ -0,0 +1,67 @@ +extraHosts: ENC[AES256_GCM,data:nuEU+Tlj9BBEO/459B7u74WEdlDmvn3coWkk3JG5uqWXR1G4tk6H8EvQAY/xAuqcM01T4psaeqQTxZA+U626zMQ++vOsYwI8cch8m0xIkKKJ3Ztyqeip8egK2xPywdJp69Z5XhweF3RlxPBTroMcCoqHG0rFQmPuwaWrM/DJ6HQBGqKA3wmaYXAC4OLFVGNzLNLfWD85PAxK1YTJnClaerFdwsxm9tq+HNg7zEnOUVyQjm2l16MKkV1kybddNFc6SKHmm2e/XYNQ85eRm1ALq1v1WRPLaa87MsPLM6svwNy5hEMX+AQKfGBL4hLUKOw+yPktfSnGhj8uDO6IUTjySzkgdYIu37E8ozN8CZ2m+5wYDjf1NU34/yUo2p3RZISuy52qEhGE0jsIeDiC6KMPs6/dHKpxbkRVhe7ZWpZvee7dhWyAkW4lk+MA1p3OklCBdTn8JcrAlVcKf0n1+XyK5ua0q5ja6UKg1Q5Y1LGFPInt+styJ65HdvqBcdLiG7DCQYHGpWGIeSNglbAKPMCeBCablN/2gLLYOK08RXwwSAj1V5lCXAKoc3FfnX73ELRelzLwE2MNJZCn0DqnqP0vOnzXM9ftWVODCjcIEmLUX+CL7hBNLrWcp+Q3ALQcSZsAVejpP8Iajo85R/Hc+2OtqfXijoJNacaMgKCX/5ZWOFEwNUdto3xSRQXu2Ck//F4F/0Ez6yqOFux1byjdyHDbGGdFz02DTZUkOtsPVssyqz1nEHepDQM0EmAAxAR6D8hHOnZGesfqbS+5Xd3+KlfxyFC2mHDxK4WZPCHTAEsenWEiQTGfaOT+1bpbimRfUcqiRXukSUeHY2cKf/reNw0MT7t5n1mvidihP3sJuc573ViUlG+Ts8ctyZ/+tKU2aCMz3wevPzZNiIVqXsB2lC8c,iv:MnbM30XhdQFOPmc4x/a7YaDmnCDCFHS2Nm8plh+raSo=,tag:SpHUqyeSVdtf8uk4SyjmOA==,type:str] +mopidy: + spotify: ENC[AES256_GCM,data:SaDT0iSWhsgVOi1s+Nzbr0Mur3t2Zd9z/KIUshGWtbPfkXXIoiJeJFtoZIz5NL/t5FooYsNfU1mGYgDeVYSD4BPibW8hiCYrX6L6OX+Q6ZEWXXx/1eBEs2/q0BrWGvy7frcurq/Px4R3ax0dXJe/YKbpAtU7+bQl,iv:F2zT+uMVBMnSEZqgcRmV8/fc3G/g2fKDuHuBzkyBRN0=,tag:CD8fuOQfe6QCrj4BUh0/xw==,type:str] + bandcamp: ENC[AES256_GCM,data:diEx2fbkOR1oUav81jU5bNt/KNmbOaVzLV+G3zBUVXE7nEQpZNqVom0rgNrEVDGzH3u/IaA5eqG5ce9lE0BomeY8Z4MWI1xujhX5KsXdv21aw4UwsNgyLPuWhkN2POUMfCJlvekc/TFfFvJHyysx8aKxeI4dsg==,iv:cxx0cVkjOPG+hMD8JctJHdcICJt7ozpfRBVSCDBo6Ro=,tag:JRjwwvieGaGZJ+k56HWFaw==,type:str] +emailPassword: ENC[AES256_GCM,data:LALAvyuNN9bfa8D6ZK1YiFXRfxLOBi9kXA0N0Kr7h18eAI4hWQ==,iv:WtidILFfWCMKylax52JP+X57GfZyYlxJtiwrC6SADik=,tag:NvOrsL3fbmxQZp06GZhUZA==,type:str] +ssh: + hosts: ENC[AES256_GCM,data:jLLehzuBuBh22ZukRlqjQJNBg0ri8go58SJfs4GjNqNdvI/H0NWRS0apqLPzERkbpPipex3kUiFIc6BH+usSSpfh/MWico8qZDKVD7Ekx6F8k45I2Pq+mbLsMEo3XfjcnfYgDWn2I7/jyidBsvA+m9VnjU8/Cnk5O/YeIZQRvfOZ4xc8zw7C/vqmxsNi2KZr+2N23L+eetoKM4J6AigmINH41wAL3/RlB0oCpjSHSkbp7Glu2LlyJygS52p9m5pq4QBXtoiu5AJ6qG17LrypmDjfxE2zU2R3Zu6VLbs4zWQY2+W36j33Fm5nMkMMPJAEdRR27HPxM2EAEuH4OI1Jbup669sln9nJxnO2zYveplNPsAb3a16D4L9rwSzUd1s2W+NlqBSYdyAktuvtPWf1vAg9+Fob9jUgUFGTQpNF8Xj1n+DqvXlLQknsB/7EhNSSnYyQS36wHF9KBHJwexpYbhnGiMuLjN6KXbr/YYawocSA/5o8s6X/tRXKMkXtZjoEsyr1aNMj+4gSHaSUOG78r3VwAHLOXNez67xFpKMa/IQfQhj2Zng8142hhL4hPyNtuTOK3oVvPjZtAfbfxesUi+Zx2VhaJsnmj6J4gAOWU9nVpol67V0hNSD4LMUOZwwPst11IyJsXjkKKY0iy7ykFMTk6KalkVUqlYOmQRIXtBE9sD4esC+FGH1ONi3n0tbG7YivmV3YSmxk0RvQ/YlKGOchKpPH/bzN/X+NZh6A3Uk5uDsqU+GOjfDY2yIgetw4FAQ42YMxNmTJjq6MpcaETb5eQm8wee4QaVODocXHyknfWs6FYGNUjQpYp3+zxKJovHuKQcFgug3t8Si5hKnQz6KDZNaoDE0UMBR2ABbAX1Bcvu0lLHzaPXpGfXyoAe+B3MwF9/TTVkCNNYhNKm63P7qUuIbKLLCDXH6e4y5YiIF8Sl9jF/kR8v8MbLgrAROx8NlTm5CqNhQWOPQQyQXvXEl5hwHyF9ptrXUB9wIe,iv:6Lzbf+DBTfaZj7NhTJ07dVPuaViP61V4N2QHPTEFzMQ=,tag:8t4c0DJmAwg/0qRLBW4vCQ==,type:str] +sops: + age: + - recipient: age1ajemtm502nn2n4q7v4j8meyd5mxtcqngkkedxq2pqzuwu78zp93qnw8q48 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiYU1MR2w4Njh2cVBocmJq + YkxvSmVsWDdGT0h0S3NSbDYxb21EVTlxT21nCjB3WlVmK0hkR1B6Z2lhbndvNFdC + aE9YMHphU1JoV2hwZ0RITXhHZnJmeTAKLS0tIDk4akc0T1FvbURLRFpXNHlRQ3Vx + TUZMTENMbVNjeVFxMGVSc2FpZ0dXcDgKcacaFS2diAKeKwmVz7KghKjkNI2ij4Ns + fYSd8sq/bEDTvn1wNpF1zLmzX9jmoXc5iORuRKaYcT8OaoUX7SsFvQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age197lfdanym647wdaz9uy8hrfqjwj9fs8rm7vs3fsrctceu8mr9gms2jedhz + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUNlhkZzFoa21tR244dVJ0 + cXJWbDA0eVBrZWU4QVRVQm85bVVScFdYbHdnCjRWQWRNajIyQ0JoYTFFQ3RsOFA4 + cTZGNVhCN2k0NHBMb1Z4VmVqRzNjbEkKLS0tIFhJTVBCM0E4dTkweld6WUx5Z1hQ + WXdwVFJ3cXQzUnFPUnV2NzdqcWwwZkkKqS9IQpB/MjnsVQ4IfIRtH6FESzLkdHq/ + GJnMHt0VcLt/gYrz+lrPc1ecQwNvVGH2Qt++BbSJxUFftoDLdEMlig== + -----END AGE ENCRYPTED FILE----- + - recipient: age17pn6suvz2f7zmrm9zxj5hr0putvcvdamqxqt7ewhncgg6ccgmp2qr00xm2 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtcVZPWVNBc1pFWm8zN3hm + M1RtenlCbGl3Q0xhWlRWN1BmOUNDK3I0cVQwCk82Vm5IcmZZeVRBdlVUb0NtTXdz + QTlVMEhCWkpJN0JOM09mSGtqbzl5ZUkKLS0tIE4vTGhEQlRDZ1Vma0VEQ0xtcU9V + MitPc29VYUV3UmJSNXdmMUhwck9MOXMKLXHEKpNvzModiTR1Q6cE1xKSGewV/9PJ + rEbTgsa0E9C4vm5sDKjSjuvpSF9tNOSByf5So5kzX0ZTxgjdTjsFbw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1cnnpnglkvgw5ffv8qpgwpqvj203lh4uwt698y9mxjwklxt8nysmsa8hepn + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkeUlIL2QxQlhGN3RqOFZR + K1p1bjc5R00yclEzL0hYY0c2OFJhRmN4Y0JvCkpIL0Q4Y1Nic3pFYjNIM1hMK2w2 + cFNGNVhHcW85R2loZ3JveVVZNGptd1kKLS0tIGYvYjlTMzRzUUNlM3padDJHNkFm + VGJHL2c4Z05pTWlxellFMG4rRlp1MkUK4mwb2jMlfHb0ISInZKwbm9+EqBzWfZNU + +L/WahvTo4Fe9uSOJffpSMleH0ZJS35loCJE5WIdmGnRQB6Mw7LWag== + -----END AGE ENCRYPTED FILE----- + - recipient: age1g68hxv73llkyc7etzh499ztcrt93pwawy0n8p93px4taqu58mehsp88vjq + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIR3FWcElFL2RBRmdFS1cy + emRTM201a1ltWndUcDJ5RXptd1RTNHdvWXpNCkxBTXZCNUxvd1dXMDhHK0ZFVUI1 + c2VkRlJJbDNYSzF0djJXN0J4YXltam8KLS0tIEFTZjdWd0NQTVEyU1Q4UCtQVGhy + K3VUdlpjd0M3RVBHOVVjc04yZzV4UkUKcB8r+FiqZqwsxj40hCtVePnfIZ3S8DFR + tgSRDMp8eEm6vXHbbf49E/cpV4iBwVel9zAe64tYs7atk9dcgMmOpw== + -----END AGE ENCRYPTED FILE----- + - recipient: age1awytvphvty4f9wmdn86xnjg9kgetqjx8qlwj5d2882t4fyyzy58s3vg5k4 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0TkVLUnFDMnVoT3BUM0kr + ZU5hZE1teGF1M21SbmY5MHZTMytKeWpkYnk0CmkwNXlBMDR1cEp2MkZPeWUyU0hZ + Wlp4SFIwZUNQa25BRENsYWNoZmZoNjQKLS0tIEtIU3NRVS94SW80VXVGZy9hRkNQ + QmJKNDJUY0RSakhwNWlkOVpib0trc1kK0tQxD9I82pjfs54eruu+IjzVUmcVBCPw + 9mp1xKiYRRMXt3YQn6MPiyuuX3l3UB5MH0RJMNtRq0D961rs+iiS5A== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-05-04T01:05:13Z" + mac: ENC[AES256_GCM,data:/wuo0bg48xlbP074JJ0rtmclWMG9vjlJnWjJnUaz45m+Gqj4IzA5ctSZdNnFTb7/CXkynJdFHme4/Nz8I/6+zzTFBeo/nVw43s1n0XmMqVYb2U/FTikvCMowHNnfMTY5Q83jD1MtE3XsRSCzxe649D4Zbcja8XG42v5rOt3geMA=,iv:n/yFp5f+LK8JaikifjRuieNtmcazl2VNz8rIzbvgBO8=,tag:Fs4+St1lxMn+VdEoP+Eo8g==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/users/modules/basics.nix b/users/modules/basics.nix new file mode 100644 index 0000000..5159beb --- /dev/null +++ b/users/modules/basics.nix @@ -0,0 +1,10 @@ +{ + programs = { + fd.enable = true; + fzf.enable = true; + home-manager.enable = true; + htop.enable = true; + jq.enable = true; + ripgrep.enable = true; + }; +} diff --git a/users/modules/bat.nix b/users/modules/bat.nix new file mode 100644 index 0000000..b51c0fb --- /dev/null +++ b/users/modules/bat.nix @@ -0,0 +1,25 @@ +{ + pkgs, + config, + lib, + ... +}: +with lib; let + cfg = config.modules.bat; +in { + options.modules.bat.extras = mkEnableOption "Enables extra packages for bat."; + config.programs.bat = { + enable = true; + config = { + theme = "Nord"; + map-syntax = [ + ".spacemacs*:Lisp" + ]; + }; + extraPackages = mkIf cfg.extras (with pkgs.bat-extras; [ + batman + batpipe + batgrep + ]); + }; +} diff --git a/users/modules/btop.nix b/users/modules/btop.nix new file mode 100644 index 0000000..a64b156 --- /dev/null +++ b/users/modules/btop.nix @@ -0,0 +1,24 @@ +{pkgs, ...}: { + programs.btop = { + enable = true; + package = pkgs.btop.override { + rocmSupport = true; + cudaSupport = true; + }; + settings = { + color_theme = "${pkgs.btop}/share/btop/themes/nord.theme"; + cpu_bottom = false; + cpu_sensor = "auto"; + io_graph_combined = false; + io_mode = true; + only_physical = true; + proc_tree = true; + rounded_corners = true; + show_disks = true; + show_gpu_info = "on"; + show_uptime = true; + theme_background = true; + vim_keys = false; + }; + }; +} diff --git a/users/modules/default.nix b/users/modules/default.nix new file mode 100644 index 0000000..03bdd59 --- /dev/null +++ b/users/modules/default.nix @@ -0,0 +1,16 @@ +{ + imports = [ + ./basics.nix + ./bat.nix + ./btop.nix + ./direnv.nix + ./eza.nix + ./mopidy.nix + ./nh.nix + ./shell + ./ssh.nix + ./tealdeer.nix + ./tmux.nix + ./vcs + ]; +} diff --git a/users/modules/direnv.nix b/users/modules/direnv.nix new file mode 100644 index 0000000..abb06fd --- /dev/null +++ b/users/modules/direnv.nix @@ -0,0 +1,7 @@ +{ + programs.direnv = { + enable = true; + config.global.load_dotenv = true; + nix-direnv.enable = true; + }; +} diff --git a/users/modules/emacs.nix b/users/modules/emacs.nix new file mode 100644 index 0000000..444d6b8 --- /dev/null +++ b/users/modules/emacs.nix @@ -0,0 +1,36 @@ +{ + pkgs, + config, + lib, + ... +}: let + emacsDefaultPackage = with pkgs; ((emacsPackagesFor emacsNativeComp).emacsWithPackages ( + epkgs: [ + epkgs.vterm + epkgs.mu4e + epkgs.pdf-tools + ] + )); + cfg = config.modules.emacs; +in { + options.modules.emacs = { + enable = lib.mkEnableOption "enables Emacs"; + package = lib.mkOption { + type = lib.types.package; + default = emacsDefaultPackage; + }; + service = lib.mkEnableOption "enables Emacs service"; + }; + + config = { + programs.emacs = lib.mkIf cfg.enable { + enable = true; + inherit (cfg) package; + }; + services.emacs = lib.mkIf cfg.service { + enable = true; + inherit (cfg) package; + startWithUserSession = "graphical"; + }; + }; +} diff --git a/users/modules/emoji.nix b/users/modules/emoji.nix new file mode 100644 index 0000000..5c70daf --- /dev/null +++ b/users/modules/emoji.nix @@ -0,0 +1,4739 @@ +{ + home.file.".config/emoji".text = '' + # Parsed from https://unicode.org/Public/emoji/15.0/emoji-test.txt + # on 2023-03-03 + 😀 grinning face + 😃 grinning face with big eyes + 😄 grinning face with smiling eyes + 😁 beaming face with smiling eyes + 😆 grinning squinting face + 😅 grinning face with sweat + 🤣 rolling on the floor laughing + 😂 face with tears of joy + 🙂 slightly smiling face + 🙃 upside-down face + 🫠 melting face + 😉 winking face + 😊 smiling face with smiling eyes + 😇 smiling face with halo + 🥰 smiling face with hearts + 😍 smiling face with heart-eyes + 🤩 star-struck + 😘 face blowing a kiss + 😗 kissing face + ☺️ smiling face + ☺ smiling face + 😚 kissing face with closed eyes + 😙 kissing face with smiling eyes + 🥲 smiling face with tear + 😋 face savoring food + 😛 face with tongue + 😜 winking face with tongue + 🤪 zany face + 😝 squinting face with tongue + 🤑 money-mouth face + 🤗 smiling face with open hands + 🤭 face with hand over mouth + 🫢 face with open eyes and hand over mouth + 🫣 face with peeking eye + 🤫 shushing face + 🤔 thinking face + 🫡 saluting face + 🤐 zipper-mouth face + 🤨 face with raised eyebrow + 😐 neutral face + 😑 expressionless face + 😶 face without mouth + 🫥 dotted line face + 😶‍🌫️ face in clouds + 😶‍🌫 face in clouds + 😏 smirking face + 😒 unamused face + 🙄 face with rolling eyes + 😬 grimacing face + 😮‍💨 face exhaling + 🤥 lying face + 🫨 shaking face + 😌 relieved face + 😔 pensive face + 😪 sleepy face + 🤤 drooling face + 😴 sleeping face + 😷 face with medical mask + 🤒 face with thermometer + 🤕 face with head-bandage + 🤢 nauseated face + 🤮 face vomiting + 🤧 sneezing face + 🥵 hot face + 🥶 cold face + 🥴 woozy face + 😵 face with crossed-out eyes + 😵‍💫 face with spiral eyes + 🤯 exploding head + 🤠 cowboy hat face + 🥳 partying face + 🥸 disguised face + 😎 smiling face with sunglasses + 🤓 nerd face + 🧐 face with monocle + 😕 confused face + 🫤 face with diagonal mouth + 😟 worried face + 🙁 slightly frowning face + ☹️ frowning face + ☹ frowning face + 😮 face with open mouth + 😯 hushed face + 😲 astonished face + 😳 flushed face + 🥺 pleading face + 🥹 face holding back tears + 😦 frowning face with open mouth + 😧 anguished face + 😨 fearful face + 😰 anxious face with sweat + 😥 sad but relieved face + 😢 crying face + 😭 loudly crying face + 😱 face screaming in fear + 😖 confounded face + 😣 persevering face + 😞 disappointed face + 😓 downcast face with sweat + 😩 weary face + 😫 tired face + 🥱 yawning face + 😤 face with steam from nose + 😡 enraged face + 😠 angry face + 🤬 face with symbols on mouth + 😈 smiling face with horns + 👿 angry face with horns + 💀 skull + ☠️ skull and crossbones + ☠ skull and crossbones + 💩 pile of poo + 🤡 clown face + 👹 ogre + 👺 goblin + 👻 ghost + 👽 alien + 👾 alien monster + 🤖 robot + 😺 grinning cat + 😸 grinning cat with smiling eyes + 😹 cat with tears of joy + 😻 smiling cat with heart-eyes + 😼 cat with wry smile + 😽 kissing cat + 🙀 weary cat + 😿 crying cat + 😾 pouting cat + 🙈 see-no-evil monkey + 🙉 hear-no-evil monkey + 🙊 speak-no-evil monkey + 💌 love letter + 💘 heart with arrow + 💝 heart with ribbon + 💖 sparkling heart + 💗 growing heart + 💓 beating heart + 💞 revolving hearts + 💕 two hearts + 💟 heart decoration + ❣️ heart exclamation + ❣ heart exclamation + 💔 broken heart + ❤️‍🔥 heart on fire + ❤‍🔥 heart on fire + ❤️‍🩹 mending heart + ❤‍🩹 mending heart + ❤️ red heart + ❤ red heart + 🩷 pink heart + 🧡 orange heart + 💛 yellow heart + 💚 green heart + 💙 blue heart + 🩵 light blue heart + 💜 purple heart + 🤎 brown heart + 🖤 black heart + 🩶 grey heart + 🤍 white heart + 💋 kiss mark + 💯 hundred points + 💢 anger symbol + 💥 collision + 💫 dizzy + 💦 sweat droplets + 💨 dashing away + 🕳️ hole + 🕳 hole + 💬 speech balloon + 👁️‍🗨️ eye in speech bubble + 👁‍🗨️ eye in speech bubble + 👁️‍🗨 eye in speech bubble + 👁‍🗨 eye in speech bubble + 🗨️ left speech bubble + 🗨 left speech bubble + 🗯️ right anger bubble + 🗯 right anger bubble + 💭 thought balloon + 💤 ZZZ + 👋 waving hand + 👋🏻 waving hand: light skin tone + 👋🏼 waving hand: medium-light skin tone + 👋🏽 waving hand: medium skin tone + 👋🏾 waving hand: medium-dark skin tone + 👋🏿 waving hand: dark skin tone + 🤚 raised back of hand + 🤚🏻 raised back of hand: light skin tone + 🤚🏼 raised back of hand: medium-light skin tone + 🤚🏽 raised back of hand: medium skin tone + 🤚🏾 raised back of hand: medium-dark skin tone + 🤚🏿 raised back of hand: dark skin tone + 🖐️ hand with fingers splayed + 🖐 hand with fingers splayed + 🖐🏻 hand with fingers splayed: light skin tone + 🖐🏼 hand with fingers splayed: medium-light skin tone + 🖐🏽 hand with fingers splayed: medium skin tone + 🖐🏾 hand with fingers splayed: medium-dark skin tone + 🖐🏿 hand with fingers splayed: dark skin tone + ✋ raised hand + ✋🏻 raised hand: light skin tone + ✋🏼 raised hand: medium-light skin tone + ✋🏽 raised hand: medium skin tone + ✋🏾 raised hand: medium-dark skin tone + ✋🏿 raised hand: dark skin tone + 🖖 vulcan salute + 🖖🏻 vulcan salute: light skin tone + 🖖🏼 vulcan salute: medium-light skin tone + 🖖🏽 vulcan salute: medium skin tone + 🖖🏾 vulcan salute: medium-dark skin tone + 🖖🏿 vulcan salute: dark skin tone + 🫱 rightwards hand + 🫱🏻 rightwards hand: light skin tone + 🫱🏼 rightwards hand: medium-light skin tone + 🫱🏽 rightwards hand: medium skin tone + 🫱🏾 rightwards hand: medium-dark skin tone + 🫱🏿 rightwards hand: dark skin tone + 🫲 leftwards hand + 🫲🏻 leftwards hand: light skin tone + 🫲🏼 leftwards hand: medium-light skin tone + 🫲🏽 leftwards hand: medium skin tone + 🫲🏾 leftwards hand: medium-dark skin tone + 🫲🏿 leftwards hand: dark skin tone + 🫳 palm down hand + 🫳🏻 palm down hand: light skin tone + 🫳🏼 palm down hand: medium-light skin tone + 🫳🏽 palm down hand: medium skin tone + 🫳🏾 palm down hand: medium-dark skin tone + 🫳🏿 palm down hand: dark skin tone + 🫴 palm up hand + 🫴🏻 palm up hand: light skin tone + 🫴🏼 palm up hand: medium-light skin tone + 🫴🏽 palm up hand: medium skin tone + 🫴🏾 palm up hand: medium-dark skin tone + 🫴🏿 palm up hand: dark skin tone + 🫷 leftwards pushing hand + 🫷🏻 leftwards pushing hand: light skin tone + 🫷🏼 leftwards pushing hand: medium-light skin tone + 🫷🏽 leftwards pushing hand: medium skin tone + 🫷🏾 leftwards pushing hand: medium-dark skin tone + 🫷🏿 leftwards pushing hand: dark skin tone + 🫸 rightwards pushing hand + 🫸🏻 rightwards pushing hand: light skin tone + 🫸🏼 rightwards pushing hand: medium-light skin tone + 🫸🏽 rightwards pushing hand: medium skin tone + 🫸🏾 rightwards pushing hand: medium-dark skin tone + 🫸🏿 rightwards pushing hand: dark skin tone + 👌 OK hand + 👌🏻 OK hand: light skin tone + 👌🏼 OK hand: medium-light skin tone + 👌🏽 OK hand: medium skin tone + 👌🏾 OK hand: medium-dark skin tone + 👌🏿 OK hand: dark skin tone + 🤌 pinched fingers + 🤌🏻 pinched fingers: light skin tone + 🤌🏼 pinched fingers: medium-light skin tone + 🤌🏽 pinched fingers: medium skin tone + 🤌🏾 pinched fingers: medium-dark skin tone + 🤌🏿 pinched fingers: dark skin tone + 🤏 pinching hand + 🤏🏻 pinching hand: light skin tone + 🤏🏼 pinching hand: medium-light skin tone + 🤏🏽 pinching hand: medium skin tone + 🤏🏾 pinching hand: medium-dark skin tone + 🤏🏿 pinching hand: dark skin tone + ✌️ victory hand + ✌ victory hand + ✌🏻 victory hand: light skin tone + ✌🏼 victory hand: medium-light skin tone + ✌🏽 victory hand: medium skin tone + ✌🏾 victory hand: medium-dark skin tone + ✌🏿 victory hand: dark skin tone + 🤞 crossed fingers + 🤞🏻 crossed fingers: light skin tone + 🤞🏼 crossed fingers: medium-light skin tone + 🤞🏽 crossed fingers: medium skin tone + 🤞🏾 crossed fingers: medium-dark skin tone + 🤞🏿 crossed fingers: dark skin tone + 🫰 hand with index finger and thumb crossed + 🫰🏻 hand with index finger and thumb crossed: light skin tone + 🫰🏼 hand with index finger and thumb crossed: medium-light skin tone + 🫰🏽 hand with index finger and thumb crossed: medium skin tone + 🫰🏾 hand with index finger and thumb crossed: medium-dark skin tone + 🫰🏿 hand with index finger and thumb crossed: dark skin tone + 🤟 love-you gesture + 🤟🏻 love-you gesture: light skin tone + 🤟🏼 love-you gesture: medium-light skin tone + 🤟🏽 love-you gesture: medium skin tone + 🤟🏾 love-you gesture: medium-dark skin tone + 🤟🏿 love-you gesture: dark skin tone + 🤘 sign of the horns + 🤘🏻 sign of the horns: light skin tone + 🤘🏼 sign of the horns: medium-light skin tone + 🤘🏽 sign of the horns: medium skin tone + 🤘🏾 sign of the horns: medium-dark skin tone + 🤘🏿 sign of the horns: dark skin tone + 🤙 call me hand + 🤙🏻 call me hand: light skin tone + 🤙🏼 call me hand: medium-light skin tone + 🤙🏽 call me hand: medium skin tone + 🤙🏾 call me hand: medium-dark skin tone + 🤙🏿 call me hand: dark skin tone + 👈 backhand index pointing left + 👈🏻 backhand index pointing left: light skin tone + 👈🏼 backhand index pointing left: medium-light skin tone + 👈🏽 backhand index pointing left: medium skin tone + 👈🏾 backhand index pointing left: medium-dark skin tone + 👈🏿 backhand index pointing left: dark skin tone + 👉 backhand index pointing right + 👉🏻 backhand index pointing right: light skin tone + 👉🏼 backhand index pointing right: medium-light skin tone + 👉🏽 backhand index pointing right: medium skin tone + 👉🏾 backhand index pointing right: medium-dark skin tone + 👉🏿 backhand index pointing right: dark skin tone + 👆 backhand index pointing up + 👆🏻 backhand index pointing up: light skin tone + 👆🏼 backhand index pointing up: medium-light skin tone + 👆🏽 backhand index pointing up: medium skin tone + 👆🏾 backhand index pointing up: medium-dark skin tone + 👆🏿 backhand index pointing up: dark skin tone + 🖕 middle finger + 🖕🏻 middle finger: light skin tone + 🖕🏼 middle finger: medium-light skin tone + 🖕🏽 middle finger: medium skin tone + 🖕🏾 middle finger: medium-dark skin tone + 🖕🏿 middle finger: dark skin tone + 👇 backhand index pointing down + 👇🏻 backhand index pointing down: light skin tone + 👇🏼 backhand index pointing down: medium-light skin tone + 👇🏽 backhand index pointing down: medium skin tone + 👇🏾 backhand index pointing down: medium-dark skin tone + 👇🏿 backhand index pointing down: dark skin tone + ☝️ index pointing up + ☝ index pointing up + ☝🏻 index pointing up: light skin tone + ☝🏼 index pointing up: medium-light skin tone + ☝🏽 index pointing up: medium skin tone + ☝🏾 index pointing up: medium-dark skin tone + ☝🏿 index pointing up: dark skin tone + 🫵 index pointing at the viewer + 🫵🏻 index pointing at the viewer: light skin tone + 🫵🏼 index pointing at the viewer: medium-light skin tone + 🫵🏽 index pointing at the viewer: medium skin tone + 🫵🏾 index pointing at the viewer: medium-dark skin tone + 🫵🏿 index pointing at the viewer: dark skin tone + 👍 thumbs up + 👍🏻 thumbs up: light skin tone + 👍🏼 thumbs up: medium-light skin tone + 👍🏽 thumbs up: medium skin tone + 👍🏾 thumbs up: medium-dark skin tone + 👍🏿 thumbs up: dark skin tone + 👎 thumbs down + 👎🏻 thumbs down: light skin tone + 👎🏼 thumbs down: medium-light skin tone + 👎🏽 thumbs down: medium skin tone + 👎🏾 thumbs down: medium-dark skin tone + 👎🏿 thumbs down: dark skin tone + ✊ raised fist + ✊🏻 raised fist: light skin tone + ✊🏼 raised fist: medium-light skin tone + ✊🏽 raised fist: medium skin tone + ✊🏾 raised fist: medium-dark skin tone + ✊🏿 raised fist: dark skin tone + 👊 oncoming fist + 👊🏻 oncoming fist: light skin tone + 👊🏼 oncoming fist: medium-light skin tone + 👊🏽 oncoming fist: medium skin tone + 👊🏾 oncoming fist: medium-dark skin tone + 👊🏿 oncoming fist: dark skin tone + 🤛 left-facing fist + 🤛🏻 left-facing fist: light skin tone + 🤛🏼 left-facing fist: medium-light skin tone + 🤛🏽 left-facing fist: medium skin tone + 🤛🏾 left-facing fist: medium-dark skin tone + 🤛🏿 left-facing fist: dark skin tone + 🤜 right-facing fist + 🤜🏻 right-facing fist: light skin tone + 🤜🏼 right-facing fist: medium-light skin tone + 🤜🏽 right-facing fist: medium skin tone + 🤜🏾 right-facing fist: medium-dark skin tone + 🤜🏿 right-facing fist: dark skin tone + 👏 clapping hands + 👏🏻 clapping hands: light skin tone + 👏🏼 clapping hands: medium-light skin tone + 👏🏽 clapping hands: medium skin tone + 👏🏾 clapping hands: medium-dark skin tone + 👏🏿 clapping hands: dark skin tone + 🙌 raising hands + 🙌🏻 raising hands: light skin tone + 🙌🏼 raising hands: medium-light skin tone + 🙌🏽 raising hands: medium skin tone + 🙌🏾 raising hands: medium-dark skin tone + 🙌🏿 raising hands: dark skin tone + 🫶 heart hands + 🫶🏻 heart hands: light skin tone + 🫶🏼 heart hands: medium-light skin tone + 🫶🏽 heart hands: medium skin tone + 🫶🏾 heart hands: medium-dark skin tone + 🫶🏿 heart hands: dark skin tone + 👐 open hands + 👐🏻 open hands: light skin tone + 👐🏼 open hands: medium-light skin tone + 👐🏽 open hands: medium skin tone + 👐🏾 open hands: medium-dark skin tone + 👐🏿 open hands: dark skin tone + 🤲 palms up together + 🤲🏻 palms up together: light skin tone + 🤲🏼 palms up together: medium-light skin tone + 🤲🏽 palms up together: medium skin tone + 🤲🏾 palms up together: medium-dark skin tone + 🤲🏿 palms up together: dark skin tone + 🤝 handshake + 🤝🏻 handshake: light skin tone + 🤝🏼 handshake: medium-light skin tone + 🤝🏽 handshake: medium skin tone + 🤝🏾 handshake: medium-dark skin tone + 🤝🏿 handshake: dark skin tone + 🫱🏻‍🫲🏼 handshake: light skin tone, medium-light skin tone + 🫱🏻‍🫲🏽 handshake: light skin tone, medium skin tone + 🫱🏻‍🫲🏾 handshake: light skin tone, medium-dark skin tone + 🫱🏻‍🫲🏿 handshake: light skin tone, dark skin tone + 🫱🏼‍🫲🏻 handshake: medium-light skin tone, light skin tone + 🫱🏼‍🫲🏽 handshake: medium-light skin tone, medium skin tone + 🫱🏼‍🫲🏾 handshake: medium-light skin tone, medium-dark skin tone + 🫱🏼‍🫲🏿 handshake: medium-light skin tone, dark skin tone + 🫱🏽‍🫲🏻 handshake: medium skin tone, light skin tone + 🫱🏽‍🫲🏼 handshake: medium skin tone, medium-light skin tone + 🫱🏽‍🫲🏾 handshake: medium skin tone, medium-dark skin tone + 🫱🏽‍🫲🏿 handshake: medium skin tone, dark skin tone + 🫱🏾‍🫲🏻 handshake: medium-dark skin tone, light skin tone + 🫱🏾‍🫲🏼 handshake: medium-dark skin tone, medium-light skin tone + 🫱🏾‍🫲🏽 handshake: medium-dark skin tone, medium skin tone + 🫱🏾‍🫲🏿 handshake: medium-dark skin tone, dark skin tone + 🫱🏿‍🫲🏻 handshake: dark skin tone, light skin tone + 🫱🏿‍🫲🏼 handshake: dark skin tone, medium-light skin tone + 🫱🏿‍🫲🏽 handshake: dark skin tone, medium skin tone + 🫱🏿‍🫲🏾 handshake: dark skin tone, medium-dark skin tone + 🙏 folded hands + 🙏🏻 folded hands: light skin tone + 🙏🏼 folded hands: medium-light skin tone + 🙏🏽 folded hands: medium skin tone + 🙏🏾 folded hands: medium-dark skin tone + 🙏🏿 folded hands: dark skin tone + ✍️ writing hand + ✍ writing hand + ✍🏻 writing hand: light skin tone + ✍🏼 writing hand: medium-light skin tone + ✍🏽 writing hand: medium skin tone + ✍🏾 writing hand: medium-dark skin tone + ✍🏿 writing hand: dark skin tone + 💅 nail polish + 💅🏻 nail polish: light skin tone + 💅🏼 nail polish: medium-light skin tone + 💅🏽 nail polish: medium skin tone + 💅🏾 nail polish: medium-dark skin tone + 💅🏿 nail polish: dark skin tone + 🤳 selfie + 🤳🏻 selfie: light skin tone + 🤳🏼 selfie: medium-light skin tone + 🤳🏽 selfie: medium skin tone + 🤳🏾 selfie: medium-dark skin tone + 🤳🏿 selfie: dark skin tone + 💪 flexed biceps + 💪🏻 flexed biceps: light skin tone + 💪🏼 flexed biceps: medium-light skin tone + 💪🏽 flexed biceps: medium skin tone + 💪🏾 flexed biceps: medium-dark skin tone + 💪🏿 flexed biceps: dark skin tone + 🦾 mechanical arm + 🦿 mechanical leg + 🦵 leg + 🦵🏻 leg: light skin tone + 🦵🏼 leg: medium-light skin tone + 🦵🏽 leg: medium skin tone + 🦵🏾 leg: medium-dark skin tone + 🦵🏿 leg: dark skin tone + 🦶 foot + 🦶🏻 foot: light skin tone + 🦶🏼 foot: medium-light skin tone + 🦶🏽 foot: medium skin tone + 🦶🏾 foot: medium-dark skin tone + 🦶🏿 foot: dark skin tone + 👂 ear + 👂🏻 ear: light skin tone + 👂🏼 ear: medium-light skin tone + 👂🏽 ear: medium skin tone + 👂🏾 ear: medium-dark skin tone + 👂🏿 ear: dark skin tone + 🦻 ear with hearing aid + 🦻🏻 ear with hearing aid: light skin tone + 🦻🏼 ear with hearing aid: medium-light skin tone + 🦻🏽 ear with hearing aid: medium skin tone + 🦻🏾 ear with hearing aid: medium-dark skin tone + 🦻🏿 ear with hearing aid: dark skin tone + 👃 nose + 👃🏻 nose: light skin tone + 👃🏼 nose: medium-light skin tone + 👃🏽 nose: medium skin tone + 👃🏾 nose: medium-dark skin tone + 👃🏿 nose: dark skin tone + 🧠 brain + 🫀 anatomical heart + 🫁 lungs + 🦷 tooth + 🦴 bone + 👀 eyes + 👁️ eye + 👁 eye + 👅 tongue + 👄 mouth + 🫦 biting lip + 👶 baby + 👶🏻 baby: light skin tone + 👶🏼 baby: medium-light skin tone + 👶🏽 baby: medium skin tone + 👶🏾 baby: medium-dark skin tone + 👶🏿 baby: dark skin tone + 🧒 child + 🧒🏻 child: light skin tone + 🧒🏼 child: medium-light skin tone + 🧒🏽 child: medium skin tone + 🧒🏾 child: medium-dark skin tone + 🧒🏿 child: dark skin tone + 👦 boy + 👦🏻 boy: light skin tone + 👦🏼 boy: medium-light skin tone + 👦🏽 boy: medium skin tone + 👦🏾 boy: medium-dark skin tone + 👦🏿 boy: dark skin tone + 👧 girl + 👧🏻 girl: light skin tone + 👧🏼 girl: medium-light skin tone + 👧🏽 girl: medium skin tone + 👧🏾 girl: medium-dark skin tone + 👧🏿 girl: dark skin tone + 🧑 person + 🧑🏻 person: light skin tone + 🧑🏼 person: medium-light skin tone + 🧑🏽 person: medium skin tone + 🧑🏾 person: medium-dark skin tone + 🧑🏿 person: dark skin tone + 👱 person: blond hair + 👱🏻 person: light skin tone, blond hair + 👱🏼 person: medium-light skin tone, blond hair + 👱🏽 person: medium skin tone, blond hair + 👱🏾 person: medium-dark skin tone, blond hair + 👱🏿 person: dark skin tone, blond hair + 👨 man + 👨🏻 man: light skin tone + 👨🏼 man: medium-light skin tone + 👨🏽 man: medium skin tone + 👨🏾 man: medium-dark skin tone + 👨🏿 man: dark skin tone + 🧔 person: beard + 🧔🏻 person: light skin tone, beard + 🧔🏼 person: medium-light skin tone, beard + 🧔🏽 person: medium skin tone, beard + 🧔🏾 person: medium-dark skin tone, beard + 🧔🏿 person: dark skin tone, beard + 🧔‍♂️ man: beard + 🧔‍♂ man: beard + 🧔🏻‍♂️ man: light skin tone, beard + 🧔🏻‍♂ man: light skin tone, beard + 🧔🏼‍♂️ man: medium-light skin tone, beard + 🧔🏼‍♂ man: medium-light skin tone, beard + 🧔🏽‍♂️ man: medium skin tone, beard + 🧔🏽‍♂ man: medium skin tone, beard + 🧔🏾‍♂️ man: medium-dark skin tone, beard + 🧔🏾‍♂ man: medium-dark skin tone, beard + 🧔🏿‍♂️ man: dark skin tone, beard + 🧔🏿‍♂ man: dark skin tone, beard + 🧔‍♀️ woman: beard + 🧔‍♀ woman: beard + 🧔🏻‍♀️ woman: light skin tone, beard + 🧔🏻‍♀ woman: light skin tone, beard + 🧔🏼‍♀️ woman: medium-light skin tone, beard + 🧔🏼‍♀ woman: medium-light skin tone, beard + 🧔🏽‍♀️ woman: medium skin tone, beard + 🧔🏽‍♀ woman: medium skin tone, beard + 🧔🏾‍♀️ woman: medium-dark skin tone, beard + 🧔🏾‍♀ woman: medium-dark skin tone, beard + 🧔🏿‍♀️ woman: dark skin tone, beard + 🧔🏿‍♀ woman: dark skin tone, beard + 👨‍🦰 man: red hair + 👨🏻‍🦰 man: light skin tone, red hair + 👨🏼‍🦰 man: medium-light skin tone, red hair + 👨🏽‍🦰 man: medium skin tone, red hair + 👨🏾‍🦰 man: medium-dark skin tone, red hair + 👨🏿‍🦰 man: dark skin tone, red hair + 👨‍🦱 man: curly hair + 👨🏻‍🦱 man: light skin tone, curly hair + 👨🏼‍🦱 man: medium-light skin tone, curly hair + 👨🏽‍🦱 man: medium skin tone, curly hair + 👨🏾‍🦱 man: medium-dark skin tone, curly hair + 👨🏿‍🦱 man: dark skin tone, curly hair + 👨‍🦳 man: white hair + 👨🏻‍🦳 man: light skin tone, white hair + 👨🏼‍🦳 man: medium-light skin tone, white hair + 👨🏽‍🦳 man: medium skin tone, white hair + 👨🏾‍🦳 man: medium-dark skin tone, white hair + 👨🏿‍🦳 man: dark skin tone, white hair + 👨‍🦲 man: bald + 👨🏻‍🦲 man: light skin tone, bald + 👨🏼‍🦲 man: medium-light skin tone, bald + 👨🏽‍🦲 man: medium skin tone, bald + 👨🏾‍🦲 man: medium-dark skin tone, bald + 👨🏿‍🦲 man: dark skin tone, bald + 👩 woman + 👩🏻 woman: light skin tone + 👩🏼 woman: medium-light skin tone + 👩🏽 woman: medium skin tone + 👩🏾 woman: medium-dark skin tone + 👩🏿 woman: dark skin tone + 👩‍🦰 woman: red hair + 👩🏻‍🦰 woman: light skin tone, red hair + 👩🏼‍🦰 woman: medium-light skin tone, red hair + 👩🏽‍🦰 woman: medium skin tone, red hair + 👩🏾‍🦰 woman: medium-dark skin tone, red hair + 👩🏿‍🦰 woman: dark skin tone, red hair + 🧑‍🦰 person: red hair + 🧑🏻‍🦰 person: light skin tone, red hair + 🧑🏼‍🦰 person: medium-light skin tone, red hair + 🧑🏽‍🦰 person: medium skin tone, red hair + 🧑🏾‍🦰 person: medium-dark skin tone, red hair + 🧑🏿‍🦰 person: dark skin tone, red hair + 👩‍🦱 woman: curly hair + 👩🏻‍🦱 woman: light skin tone, curly hair + 👩🏼‍🦱 woman: medium-light skin tone, curly hair + 👩🏽‍🦱 woman: medium skin tone, curly hair + 👩🏾‍🦱 woman: medium-dark skin tone, curly hair + 👩🏿‍🦱 woman: dark skin tone, curly hair + 🧑‍🦱 person: curly hair + 🧑🏻‍🦱 person: light skin tone, curly hair + 🧑🏼‍🦱 person: medium-light skin tone, curly hair + 🧑🏽‍🦱 person: medium skin tone, curly hair + 🧑🏾‍🦱 person: medium-dark skin tone, curly hair + 🧑🏿‍🦱 person: dark skin tone, curly hair + 👩‍🦳 woman: white hair + 👩🏻‍🦳 woman: light skin tone, white hair + 👩🏼‍🦳 woman: medium-light skin tone, white hair + 👩🏽‍🦳 woman: medium skin tone, white hair + 👩🏾‍🦳 woman: medium-dark skin tone, white hair + 👩🏿‍🦳 woman: dark skin tone, white hair + 🧑‍🦳 person: white hair + 🧑🏻‍🦳 person: light skin tone, white hair + 🧑🏼‍🦳 person: medium-light skin tone, white hair + 🧑🏽‍🦳 person: medium skin tone, white hair + 🧑🏾‍🦳 person: medium-dark skin tone, white hair + 🧑🏿‍🦳 person: dark skin tone, white hair + 👩‍🦲 woman: bald + 👩🏻‍🦲 woman: light skin tone, bald + 👩🏼‍🦲 woman: medium-light skin tone, bald + 👩🏽‍🦲 woman: medium skin tone, bald + 👩🏾‍🦲 woman: medium-dark skin tone, bald + 👩🏿‍🦲 woman: dark skin tone, bald + 🧑‍🦲 person: bald + 🧑🏻‍🦲 person: light skin tone, bald + 🧑🏼‍🦲 person: medium-light skin tone, bald + 🧑🏽‍🦲 person: medium skin tone, bald + 🧑🏾‍🦲 person: medium-dark skin tone, bald + 🧑🏿‍🦲 person: dark skin tone, bald + 👱‍♀️ woman: blond hair + 👱‍♀ woman: blond hair + 👱🏻‍♀️ woman: light skin tone, blond hair + 👱🏻‍♀ woman: light skin tone, blond hair + 👱🏼‍♀️ woman: medium-light skin tone, blond hair + 👱🏼‍♀ woman: medium-light skin tone, blond hair + 👱🏽‍♀️ woman: medium skin tone, blond hair + 👱🏽‍♀ woman: medium skin tone, blond hair + 👱🏾‍♀️ woman: medium-dark skin tone, blond hair + 👱🏾‍♀ woman: medium-dark skin tone, blond hair + 👱🏿‍♀️ woman: dark skin tone, blond hair + 👱🏿‍♀ woman: dark skin tone, blond hair + 👱‍♂️ man: blond hair + 👱‍♂ man: blond hair + 👱🏻‍♂️ man: light skin tone, blond hair + 👱🏻‍♂ man: light skin tone, blond hair + 👱🏼‍♂️ man: medium-light skin tone, blond hair + 👱🏼‍♂ man: medium-light skin tone, blond hair + 👱🏽‍♂️ man: medium skin tone, blond hair + 👱🏽‍♂ man: medium skin tone, blond hair + 👱🏾‍♂️ man: medium-dark skin tone, blond hair + 👱🏾‍♂ man: medium-dark skin tone, blond hair + 👱🏿‍♂️ man: dark skin tone, blond hair + 👱🏿‍♂ man: dark skin tone, blond hair + 🧓 older person + 🧓🏻 older person: light skin tone + 🧓🏼 older person: medium-light skin tone + 🧓🏽 older person: medium skin tone + 🧓🏾 older person: medium-dark skin tone + 🧓🏿 older person: dark skin tone + 👴 old man + 👴🏻 old man: light skin tone + 👴🏼 old man: medium-light skin tone + 👴🏽 old man: medium skin tone + 👴🏾 old man: medium-dark skin tone + 👴🏿 old man: dark skin tone + 👵 old woman + 👵🏻 old woman: light skin tone + 👵🏼 old woman: medium-light skin tone + 👵🏽 old woman: medium skin tone + 👵🏾 old woman: medium-dark skin tone + 👵🏿 old woman: dark skin tone + 🙍 person frowning + 🙍🏻 person frowning: light skin tone + 🙍🏼 person frowning: medium-light skin tone + 🙍🏽 person frowning: medium skin tone + 🙍🏾 person frowning: medium-dark skin tone + 🙍🏿 person frowning: dark skin tone + 🙍‍♂️ man frowning + 🙍‍♂ man frowning + 🙍🏻‍♂️ man frowning: light skin tone + 🙍🏻‍♂ man frowning: light skin tone + 🙍🏼‍♂️ man frowning: medium-light skin tone + 🙍🏼‍♂ man frowning: medium-light skin tone + 🙍🏽‍♂️ man frowning: medium skin tone + 🙍🏽‍♂ man frowning: medium skin tone + 🙍🏾‍♂️ man frowning: medium-dark skin tone + 🙍🏾‍♂ man frowning: medium-dark skin tone + 🙍🏿‍♂️ man frowning: dark skin tone + 🙍🏿‍♂ man frowning: dark skin tone + 🙍‍♀️ woman frowning + 🙍‍♀ woman frowning + 🙍🏻‍♀️ woman frowning: light skin tone + 🙍🏻‍♀ woman frowning: light skin tone + 🙍🏼‍♀️ woman frowning: medium-light skin tone + 🙍🏼‍♀ woman frowning: medium-light skin tone + 🙍🏽‍♀️ woman frowning: medium skin tone + 🙍🏽‍♀ woman frowning: medium skin tone + 🙍🏾‍♀️ woman frowning: medium-dark skin tone + 🙍🏾‍♀ woman frowning: medium-dark skin tone + 🙍🏿‍♀️ woman frowning: dark skin tone + 🙍🏿‍♀ woman frowning: dark skin tone + 🙎 person pouting + 🙎🏻 person pouting: light skin tone + 🙎🏼 person pouting: medium-light skin tone + 🙎🏽 person pouting: medium skin tone + 🙎🏾 person pouting: medium-dark skin tone + 🙎🏿 person pouting: dark skin tone + 🙎‍♂️ man pouting + 🙎‍♂ man pouting + 🙎🏻‍♂️ man pouting: light skin tone + 🙎🏻‍♂ man pouting: light skin tone + 🙎🏼‍♂️ man pouting: medium-light skin tone + 🙎🏼‍♂ man pouting: medium-light skin tone + 🙎🏽‍♂️ man pouting: medium skin tone + 🙎🏽‍♂ man pouting: medium skin tone + 🙎🏾‍♂️ man pouting: medium-dark skin tone + 🙎🏾‍♂ man pouting: medium-dark skin tone + 🙎🏿‍♂️ man pouting: dark skin tone + 🙎🏿‍♂ man pouting: dark skin tone + 🙎‍♀️ woman pouting + 🙎‍♀ woman pouting + 🙎🏻‍♀️ woman pouting: light skin tone + 🙎🏻‍♀ woman pouting: light skin tone + 🙎🏼‍♀️ woman pouting: medium-light skin tone + 🙎🏼‍♀ woman pouting: medium-light skin tone + 🙎🏽‍♀️ woman pouting: medium skin tone + 🙎🏽‍♀ woman pouting: medium skin tone + 🙎🏾‍♀️ woman pouting: medium-dark skin tone + 🙎🏾‍♀ woman pouting: medium-dark skin tone + 🙎🏿‍♀️ woman pouting: dark skin tone + 🙎🏿‍♀ woman pouting: dark skin tone + 🙅 person gesturing NO + 🙅🏻 person gesturing NO: light skin tone + 🙅🏼 person gesturing NO: medium-light skin tone + 🙅🏽 person gesturing NO: medium skin tone + 🙅🏾 person gesturing NO: medium-dark skin tone + 🙅🏿 person gesturing NO: dark skin tone + 🙅‍♂️ man gesturing NO + 🙅‍♂ man gesturing NO + 🙅🏻‍♂️ man gesturing NO: light skin tone + 🙅🏻‍♂ man gesturing NO: light skin tone + 🙅🏼‍♂️ man gesturing NO: medium-light skin tone + 🙅🏼‍♂ man gesturing NO: medium-light skin tone + 🙅🏽‍♂️ man gesturing NO: medium skin tone + 🙅🏽‍♂ man gesturing NO: medium skin tone + 🙅🏾‍♂️ man gesturing NO: medium-dark skin tone + 🙅🏾‍♂ man gesturing NO: medium-dark skin tone + 🙅🏿‍♂️ man gesturing NO: dark skin tone + 🙅🏿‍♂ man gesturing NO: dark skin tone + 🙅‍♀️ woman gesturing NO + 🙅‍♀ woman gesturing NO + 🙅🏻‍♀️ woman gesturing NO: light skin tone + 🙅🏻‍♀ woman gesturing NO: light skin tone + 🙅🏼‍♀️ woman gesturing NO: medium-light skin tone + 🙅🏼‍♀ woman gesturing NO: medium-light skin tone + 🙅🏽‍♀️ woman gesturing NO: medium skin tone + 🙅🏽‍♀ woman gesturing NO: medium skin tone + 🙅🏾‍♀️ woman gesturing NO: medium-dark skin tone + 🙅🏾‍♀ woman gesturing NO: medium-dark skin tone + 🙅🏿‍♀️ woman gesturing NO: dark skin tone + 🙅🏿‍♀ woman gesturing NO: dark skin tone + 🙆 person gesturing OK + 🙆🏻 person gesturing OK: light skin tone + 🙆🏼 person gesturing OK: medium-light skin tone + 🙆🏽 person gesturing OK: medium skin tone + 🙆🏾 person gesturing OK: medium-dark skin tone + 🙆🏿 person gesturing OK: dark skin tone + 🙆‍♂️ man gesturing OK + 🙆‍♂ man gesturing OK + 🙆🏻‍♂️ man gesturing OK: light skin tone + 🙆🏻‍♂ man gesturing OK: light skin tone + 🙆🏼‍♂️ man gesturing OK: medium-light skin tone + 🙆🏼‍♂ man gesturing OK: medium-light skin tone + 🙆🏽‍♂️ man gesturing OK: medium skin tone + 🙆🏽‍♂ man gesturing OK: medium skin tone + 🙆🏾‍♂️ man gesturing OK: medium-dark skin tone + 🙆🏾‍♂ man gesturing OK: medium-dark skin tone + 🙆🏿‍♂️ man gesturing OK: dark skin tone + 🙆🏿‍♂ man gesturing OK: dark skin tone + 🙆‍♀️ woman gesturing OK + 🙆‍♀ woman gesturing OK + 🙆🏻‍♀️ woman gesturing OK: light skin tone + 🙆🏻‍♀ woman gesturing OK: light skin tone + 🙆🏼‍♀️ woman gesturing OK: medium-light skin tone + 🙆🏼‍♀ woman gesturing OK: medium-light skin tone + 🙆🏽‍♀️ woman gesturing OK: medium skin tone + 🙆🏽‍♀ woman gesturing OK: medium skin tone + 🙆🏾‍♀️ woman gesturing OK: medium-dark skin tone + 🙆🏾‍♀ woman gesturing OK: medium-dark skin tone + 🙆🏿‍♀️ woman gesturing OK: dark skin tone + 🙆🏿‍♀ woman gesturing OK: dark skin tone + 💁 person tipping hand + 💁🏻 person tipping hand: light skin tone + 💁🏼 person tipping hand: medium-light skin tone + 💁🏽 person tipping hand: medium skin tone + 💁🏾 person tipping hand: medium-dark skin tone + 💁🏿 person tipping hand: dark skin tone + 💁‍♂️ man tipping hand + 💁‍♂ man tipping hand + 💁🏻‍♂️ man tipping hand: light skin tone + 💁🏻‍♂ man tipping hand: light skin tone + 💁🏼‍♂️ man tipping hand: medium-light skin tone + 💁🏼‍♂ man tipping hand: medium-light skin tone + 💁🏽‍♂️ man tipping hand: medium skin tone + 💁🏽‍♂ man tipping hand: medium skin tone + 💁🏾‍♂️ man tipping hand: medium-dark skin tone + 💁🏾‍♂ man tipping hand: medium-dark skin tone + 💁🏿‍♂️ man tipping hand: dark skin tone + 💁🏿‍♂ man tipping hand: dark skin tone + 💁‍♀️ woman tipping hand + 💁‍♀ woman tipping hand + 💁🏻‍♀️ woman tipping hand: light skin tone + 💁🏻‍♀ woman tipping hand: light skin tone + 💁🏼‍♀️ woman tipping hand: medium-light skin tone + 💁🏼‍♀ woman tipping hand: medium-light skin tone + 💁🏽‍♀️ woman tipping hand: medium skin tone + 💁🏽‍♀ woman tipping hand: medium skin tone + 💁🏾‍♀️ woman tipping hand: medium-dark skin tone + 💁🏾‍♀ woman tipping hand: medium-dark skin tone + 💁🏿‍♀️ woman tipping hand: dark skin tone + 💁🏿‍♀ woman tipping hand: dark skin tone + 🙋 person raising hand + 🙋🏻 person raising hand: light skin tone + 🙋🏼 person raising hand: medium-light skin tone + 🙋🏽 person raising hand: medium skin tone + 🙋🏾 person raising hand: medium-dark skin tone + 🙋🏿 person raising hand: dark skin tone + 🙋‍♂️ man raising hand + 🙋‍♂ man raising hand + 🙋🏻‍♂️ man raising hand: light skin tone + 🙋🏻‍♂ man raising hand: light skin tone + 🙋🏼‍♂️ man raising hand: medium-light skin tone + 🙋🏼‍♂ man raising hand: medium-light skin tone + 🙋🏽‍♂️ man raising hand: medium skin tone + 🙋🏽‍♂ man raising hand: medium skin tone + 🙋🏾‍♂️ man raising hand: medium-dark skin tone + 🙋🏾‍♂ man raising hand: medium-dark skin tone + 🙋🏿‍♂️ man raising hand: dark skin tone + 🙋🏿‍♂ man raising hand: dark skin tone + 🙋‍♀️ woman raising hand + 🙋‍♀ woman raising hand + 🙋🏻‍♀️ woman raising hand: light skin tone + 🙋🏻‍♀ woman raising hand: light skin tone + 🙋🏼‍♀️ woman raising hand: medium-light skin tone + 🙋🏼‍♀ woman raising hand: medium-light skin tone + 🙋🏽‍♀️ woman raising hand: medium skin tone + 🙋🏽‍♀ woman raising hand: medium skin tone + 🙋🏾‍♀️ woman raising hand: medium-dark skin tone + 🙋🏾‍♀ woman raising hand: medium-dark skin tone + 🙋🏿‍♀️ woman raising hand: dark skin tone + 🙋🏿‍♀ woman raising hand: dark skin tone + 🧏 deaf person + 🧏🏻 deaf person: light skin tone + 🧏🏼 deaf person: medium-light skin tone + 🧏🏽 deaf person: medium skin tone + 🧏🏾 deaf person: medium-dark skin tone + 🧏🏿 deaf person: dark skin tone + 🧏‍♂️ deaf man + 🧏‍♂ deaf man + 🧏🏻‍♂️ deaf man: light skin tone + 🧏🏻‍♂ deaf man: light skin tone + 🧏🏼‍♂️ deaf man: medium-light skin tone + 🧏🏼‍♂ deaf man: medium-light skin tone + 🧏🏽‍♂️ deaf man: medium skin tone + 🧏🏽‍♂ deaf man: medium skin tone + 🧏🏾‍♂️ deaf man: medium-dark skin tone + 🧏🏾‍♂ deaf man: medium-dark skin tone + 🧏🏿‍♂️ deaf man: dark skin tone + 🧏🏿‍♂ deaf man: dark skin tone + 🧏‍♀️ deaf woman + 🧏‍♀ deaf woman + 🧏🏻‍♀️ deaf woman: light skin tone + 🧏🏻‍♀ deaf woman: light skin tone + 🧏🏼‍♀️ deaf woman: medium-light skin tone + 🧏🏼‍♀ deaf woman: medium-light skin tone + 🧏🏽‍♀️ deaf woman: medium skin tone + 🧏🏽‍♀ deaf woman: medium skin tone + 🧏🏾‍♀️ deaf woman: medium-dark skin tone + 🧏🏾‍♀ deaf woman: medium-dark skin tone + 🧏🏿‍♀️ deaf woman: dark skin tone + 🧏🏿‍♀ deaf woman: dark skin tone + 🙇 person bowing + 🙇🏻 person bowing: light skin tone + 🙇🏼 person bowing: medium-light skin tone + 🙇🏽 person bowing: medium skin tone + 🙇🏾 person bowing: medium-dark skin tone + 🙇🏿 person bowing: dark skin tone + 🙇‍♂️ man bowing + 🙇‍♂ man bowing + 🙇🏻‍♂️ man bowing: light skin tone + 🙇🏻‍♂ man bowing: light skin tone + 🙇🏼‍♂️ man bowing: medium-light skin tone + 🙇🏼‍♂ man bowing: medium-light skin tone + 🙇🏽‍♂️ man bowing: medium skin tone + 🙇🏽‍♂ man bowing: medium skin tone + 🙇🏾‍♂️ man bowing: medium-dark skin tone + 🙇🏾‍♂ man bowing: medium-dark skin tone + 🙇🏿‍♂️ man bowing: dark skin tone + 🙇🏿‍♂ man bowing: dark skin tone + 🙇‍♀️ woman bowing + 🙇‍♀ woman bowing + 🙇🏻‍♀️ woman bowing: light skin tone + 🙇🏻‍♀ woman bowing: light skin tone + 🙇🏼‍♀️ woman bowing: medium-light skin tone + 🙇🏼‍♀ woman bowing: medium-light skin tone + 🙇🏽‍♀️ woman bowing: medium skin tone + 🙇🏽‍♀ woman bowing: medium skin tone + 🙇🏾‍♀️ woman bowing: medium-dark skin tone + 🙇🏾‍♀ woman bowing: medium-dark skin tone + 🙇🏿‍♀️ woman bowing: dark skin tone + 🙇🏿‍♀ woman bowing: dark skin tone + 🤦 person facepalming + 🤦🏻 person facepalming: light skin tone + 🤦🏼 person facepalming: medium-light skin tone + 🤦🏽 person facepalming: medium skin tone + 🤦🏾 person facepalming: medium-dark skin tone + 🤦🏿 person facepalming: dark skin tone + 🤦‍♂️ man facepalming + 🤦‍♂ man facepalming + 🤦🏻‍♂️ man facepalming: light skin tone + 🤦🏻‍♂ man facepalming: light skin tone + 🤦🏼‍♂️ man facepalming: medium-light skin tone + 🤦🏼‍♂ man facepalming: medium-light skin tone + 🤦🏽‍♂️ man facepalming: medium skin tone + 🤦🏽‍♂ man facepalming: medium skin tone + 🤦🏾‍♂️ man facepalming: medium-dark skin tone + 🤦🏾‍♂ man facepalming: medium-dark skin tone + 🤦🏿‍♂️ man facepalming: dark skin tone + 🤦🏿‍♂ man facepalming: dark skin tone + 🤦‍♀️ woman facepalming + 🤦‍♀ woman facepalming + 🤦🏻‍♀️ woman facepalming: light skin tone + 🤦🏻‍♀ woman facepalming: light skin tone + 🤦🏼‍♀️ woman facepalming: medium-light skin tone + 🤦🏼‍♀ woman facepalming: medium-light skin tone + 🤦🏽‍♀️ woman facepalming: medium skin tone + 🤦🏽‍♀ woman facepalming: medium skin tone + 🤦🏾‍♀️ woman facepalming: medium-dark skin tone + 🤦🏾‍♀ woman facepalming: medium-dark skin tone + 🤦🏿‍♀️ woman facepalming: dark skin tone + 🤦🏿‍♀ woman facepalming: dark skin tone + 🤷 person shrugging + 🤷🏻 person shrugging: light skin tone + 🤷🏼 person shrugging: medium-light skin tone + 🤷🏽 person shrugging: medium skin tone + 🤷🏾 person shrugging: medium-dark skin tone + 🤷🏿 person shrugging: dark skin tone + 🤷‍♂️ man shrugging + 🤷‍♂ man shrugging + 🤷🏻‍♂️ man shrugging: light skin tone + 🤷🏻‍♂ man shrugging: light skin tone + 🤷🏼‍♂️ man shrugging: medium-light skin tone + 🤷🏼‍♂ man shrugging: medium-light skin tone + 🤷🏽‍♂️ man shrugging: medium skin tone + 🤷🏽‍♂ man shrugging: medium skin tone + 🤷🏾‍♂️ man shrugging: medium-dark skin tone + 🤷🏾‍♂ man shrugging: medium-dark skin tone + 🤷🏿‍♂️ man shrugging: dark skin tone + 🤷🏿‍♂ man shrugging: dark skin tone + 🤷‍♀️ woman shrugging + 🤷‍♀ woman shrugging + 🤷🏻‍♀️ woman shrugging: light skin tone + 🤷🏻‍♀ woman shrugging: light skin tone + 🤷🏼‍♀️ woman shrugging: medium-light skin tone + 🤷🏼‍♀ woman shrugging: medium-light skin tone + 🤷🏽‍♀️ woman shrugging: medium skin tone + 🤷🏽‍♀ woman shrugging: medium skin tone + 🤷🏾‍♀️ woman shrugging: medium-dark skin tone + 🤷🏾‍♀ woman shrugging: medium-dark skin tone + 🤷🏿‍♀️ woman shrugging: dark skin tone + 🤷🏿‍♀ woman shrugging: dark skin tone + 🧑‍⚕️ health worker + 🧑‍⚕ health worker + 🧑🏻‍⚕️ health worker: light skin tone + 🧑🏻‍⚕ health worker: light skin tone + 🧑🏼‍⚕️ health worker: medium-light skin tone + 🧑🏼‍⚕ health worker: medium-light skin tone + 🧑🏽‍⚕️ health worker: medium skin tone + 🧑🏽‍⚕ health worker: medium skin tone + 🧑🏾‍⚕️ health worker: medium-dark skin tone + 🧑🏾‍⚕ health worker: medium-dark skin tone + 🧑🏿‍⚕️ health worker: dark skin tone + 🧑🏿‍⚕ health worker: dark skin tone + 👨‍⚕️ man health worker + 👨‍⚕ man health worker + 👨🏻‍⚕️ man health worker: light skin tone + 👨🏻‍⚕ man health worker: light skin tone + 👨🏼‍⚕️ man health worker: medium-light skin tone + 👨🏼‍⚕ man health worker: medium-light skin tone + 👨🏽‍⚕️ man health worker: medium skin tone + 👨🏽‍⚕ man health worker: medium skin tone + 👨🏾‍⚕️ man health worker: medium-dark skin tone + 👨🏾‍⚕ man health worker: medium-dark skin tone + 👨🏿‍⚕️ man health worker: dark skin tone + 👨🏿‍⚕ man health worker: dark skin tone + 👩‍⚕️ woman health worker + 👩‍⚕ woman health worker + 👩🏻‍⚕️ woman health worker: light skin tone + 👩🏻‍⚕ woman health worker: light skin tone + 👩🏼‍⚕️ woman health worker: medium-light skin tone + 👩🏼‍⚕ woman health worker: medium-light skin tone + 👩🏽‍⚕️ woman health worker: medium skin tone + 👩🏽‍⚕ woman health worker: medium skin tone + 👩🏾‍⚕️ woman health worker: medium-dark skin tone + 👩🏾‍⚕ woman health worker: medium-dark skin tone + 👩🏿‍⚕️ woman health worker: dark skin tone + 👩🏿‍⚕ woman health worker: dark skin tone + 🧑‍🎓 student + 🧑🏻‍🎓 student: light skin tone + 🧑🏼‍🎓 student: medium-light skin tone + 🧑🏽‍🎓 student: medium skin tone + 🧑🏾‍🎓 student: medium-dark skin tone + 🧑🏿‍🎓 student: dark skin tone + 👨‍🎓 man student + 👨🏻‍🎓 man student: light skin tone + 👨🏼‍🎓 man student: medium-light skin tone + 👨🏽‍🎓 man student: medium skin tone + 👨🏾‍🎓 man student: medium-dark skin tone + 👨🏿‍🎓 man student: dark skin tone + 👩‍🎓 woman student + 👩🏻‍🎓 woman student: light skin tone + 👩🏼‍🎓 woman student: medium-light skin tone + 👩🏽‍🎓 woman student: medium skin tone + 👩🏾‍🎓 woman student: medium-dark skin tone + 👩🏿‍🎓 woman student: dark skin tone + 🧑‍🏫 teacher + 🧑🏻‍🏫 teacher: light skin tone + 🧑🏼‍🏫 teacher: medium-light skin tone + 🧑🏽‍🏫 teacher: medium skin tone + 🧑🏾‍🏫 teacher: medium-dark skin tone + 🧑🏿‍🏫 teacher: dark skin tone + 👨‍🏫 man teacher + 👨🏻‍🏫 man teacher: light skin tone + 👨🏼‍🏫 man teacher: medium-light skin tone + 👨🏽‍🏫 man teacher: medium skin tone + 👨🏾‍🏫 man teacher: medium-dark skin tone + 👨🏿‍🏫 man teacher: dark skin tone + 👩‍🏫 woman teacher + 👩🏻‍🏫 woman teacher: light skin tone + 👩🏼‍🏫 woman teacher: medium-light skin tone + 👩🏽‍🏫 woman teacher: medium skin tone + 👩🏾‍🏫 woman teacher: medium-dark skin tone + 👩🏿‍🏫 woman teacher: dark skin tone + 🧑‍⚖️ judge + 🧑‍⚖ judge + 🧑🏻‍⚖️ judge: light skin tone + 🧑🏻‍⚖ judge: light skin tone + 🧑🏼‍⚖️ judge: medium-light skin tone + 🧑🏼‍⚖ judge: medium-light skin tone + 🧑🏽‍⚖️ judge: medium skin tone + 🧑🏽‍⚖ judge: medium skin tone + 🧑🏾‍⚖️ judge: medium-dark skin tone + 🧑🏾‍⚖ judge: medium-dark skin tone + 🧑🏿‍⚖️ judge: dark skin tone + 🧑🏿‍⚖ judge: dark skin tone + 👨‍⚖️ man judge + 👨‍⚖ man judge + 👨🏻‍⚖️ man judge: light skin tone + 👨🏻‍⚖ man judge: light skin tone + 👨🏼‍⚖️ man judge: medium-light skin tone + 👨🏼‍⚖ man judge: medium-light skin tone + 👨🏽‍⚖️ man judge: medium skin tone + 👨🏽‍⚖ man judge: medium skin tone + 👨🏾‍⚖️ man judge: medium-dark skin tone + 👨🏾‍⚖ man judge: medium-dark skin tone + 👨🏿‍⚖️ man judge: dark skin tone + 👨🏿‍⚖ man judge: dark skin tone + 👩‍⚖️ woman judge + 👩‍⚖ woman judge + 👩🏻‍⚖️ woman judge: light skin tone + 👩🏻‍⚖ woman judge: light skin tone + 👩🏼‍⚖️ woman judge: medium-light skin tone + 👩🏼‍⚖ woman judge: medium-light skin tone + 👩🏽‍⚖️ woman judge: medium skin tone + 👩🏽‍⚖ woman judge: medium skin tone + 👩🏾‍⚖️ woman judge: medium-dark skin tone + 👩🏾‍⚖ woman judge: medium-dark skin tone + 👩🏿‍⚖️ woman judge: dark skin tone + 👩🏿‍⚖ woman judge: dark skin tone + 🧑‍🌾 farmer + 🧑🏻‍🌾 farmer: light skin tone + 🧑🏼‍🌾 farmer: medium-light skin tone + 🧑🏽‍🌾 farmer: medium skin tone + 🧑🏾‍🌾 farmer: medium-dark skin tone + 🧑🏿‍🌾 farmer: dark skin tone + 👨‍🌾 man farmer + 👨🏻‍🌾 man farmer: light skin tone + 👨🏼‍🌾 man farmer: medium-light skin tone + 👨🏽‍🌾 man farmer: medium skin tone + 👨🏾‍🌾 man farmer: medium-dark skin tone + 👨🏿‍🌾 man farmer: dark skin tone + 👩‍🌾 woman farmer + 👩🏻‍🌾 woman farmer: light skin tone + 👩🏼‍🌾 woman farmer: medium-light skin tone + 👩🏽‍🌾 woman farmer: medium skin tone + 👩🏾‍🌾 woman farmer: medium-dark skin tone + 👩🏿‍🌾 woman farmer: dark skin tone + 🧑‍🍳 cook + 🧑🏻‍🍳 cook: light skin tone + 🧑🏼‍🍳 cook: medium-light skin tone + 🧑🏽‍🍳 cook: medium skin tone + 🧑🏾‍🍳 cook: medium-dark skin tone + 🧑🏿‍🍳 cook: dark skin tone + 👨‍🍳 man cook + 👨🏻‍🍳 man cook: light skin tone + 👨🏼‍🍳 man cook: medium-light skin tone + 👨🏽‍🍳 man cook: medium skin tone + 👨🏾‍🍳 man cook: medium-dark skin tone + 👨🏿‍🍳 man cook: dark skin tone + 👩‍🍳 woman cook + 👩🏻‍🍳 woman cook: light skin tone + 👩🏼‍🍳 woman cook: medium-light skin tone + 👩🏽‍🍳 woman cook: medium skin tone + 👩🏾‍🍳 woman cook: medium-dark skin tone + 👩🏿‍🍳 woman cook: dark skin tone + 🧑‍🔧 mechanic + 🧑🏻‍🔧 mechanic: light skin tone + 🧑🏼‍🔧 mechanic: medium-light skin tone + 🧑🏽‍🔧 mechanic: medium skin tone + 🧑🏾‍🔧 mechanic: medium-dark skin tone + 🧑🏿‍🔧 mechanic: dark skin tone + 👨‍🔧 man mechanic + 👨🏻‍🔧 man mechanic: light skin tone + 👨🏼‍🔧 man mechanic: medium-light skin tone + 👨🏽‍🔧 man mechanic: medium skin tone + 👨🏾‍🔧 man mechanic: medium-dark skin tone + 👨🏿‍🔧 man mechanic: dark skin tone + 👩‍🔧 woman mechanic + 👩🏻‍🔧 woman mechanic: light skin tone + 👩🏼‍🔧 woman mechanic: medium-light skin tone + 👩🏽‍🔧 woman mechanic: medium skin tone + 👩🏾‍🔧 woman mechanic: medium-dark skin tone + 👩🏿‍🔧 woman mechanic: dark skin tone + 🧑‍🏭 factory worker + 🧑🏻‍🏭 factory worker: light skin tone + 🧑🏼‍🏭 factory worker: medium-light skin tone + 🧑🏽‍🏭 factory worker: medium skin tone + 🧑🏾‍🏭 factory worker: medium-dark skin tone + 🧑🏿‍🏭 factory worker: dark skin tone + 👨‍🏭 man factory worker + 👨🏻‍🏭 man factory worker: light skin tone + 👨🏼‍🏭 man factory worker: medium-light skin tone + 👨🏽‍🏭 man factory worker: medium skin tone + 👨🏾‍🏭 man factory worker: medium-dark skin tone + 👨🏿‍🏭 man factory worker: dark skin tone + 👩‍🏭 woman factory worker + 👩🏻‍🏭 woman factory worker: light skin tone + 👩🏼‍🏭 woman factory worker: medium-light skin tone + 👩🏽‍🏭 woman factory worker: medium skin tone + 👩🏾‍🏭 woman factory worker: medium-dark skin tone + 👩🏿‍🏭 woman factory worker: dark skin tone + 🧑‍💼 office worker + 🧑🏻‍💼 office worker: light skin tone + 🧑🏼‍💼 office worker: medium-light skin tone + 🧑🏽‍💼 office worker: medium skin tone + 🧑🏾‍💼 office worker: medium-dark skin tone + 🧑🏿‍💼 office worker: dark skin tone + 👨‍💼 man office worker + 👨🏻‍💼 man office worker: light skin tone + 👨🏼‍💼 man office worker: medium-light skin tone + 👨🏽‍💼 man office worker: medium skin tone + 👨🏾‍💼 man office worker: medium-dark skin tone + 👨🏿‍💼 man office worker: dark skin tone + 👩‍💼 woman office worker + 👩🏻‍💼 woman office worker: light skin tone + 👩🏼‍💼 woman office worker: medium-light skin tone + 👩🏽‍💼 woman office worker: medium skin tone + 👩🏾‍💼 woman office worker: medium-dark skin tone + 👩🏿‍💼 woman office worker: dark skin tone + 🧑‍🔬 scientist + 🧑🏻‍🔬 scientist: light skin tone + 🧑🏼‍🔬 scientist: medium-light skin tone + 🧑🏽‍🔬 scientist: medium skin tone + 🧑🏾‍🔬 scientist: medium-dark skin tone + 🧑🏿‍🔬 scientist: dark skin tone + 👨‍🔬 man scientist + 👨🏻‍🔬 man scientist: light skin tone + 👨🏼‍🔬 man scientist: medium-light skin tone + 👨🏽‍🔬 man scientist: medium skin tone + 👨🏾‍🔬 man scientist: medium-dark skin tone + 👨🏿‍🔬 man scientist: dark skin tone + 👩‍🔬 woman scientist + 👩🏻‍🔬 woman scientist: light skin tone + 👩🏼‍🔬 woman scientist: medium-light skin tone + 👩🏽‍🔬 woman scientist: medium skin tone + 👩🏾‍🔬 woman scientist: medium-dark skin tone + 👩🏿‍🔬 woman scientist: dark skin tone + 🧑‍💻 technologist + 🧑🏻‍💻 technologist: light skin tone + 🧑🏼‍💻 technologist: medium-light skin tone + 🧑🏽‍💻 technologist: medium skin tone + 🧑🏾‍💻 technologist: medium-dark skin tone + 🧑🏿‍💻 technologist: dark skin tone + 👨‍💻 man technologist + 👨🏻‍💻 man technologist: light skin tone + 👨🏼‍💻 man technologist: medium-light skin tone + 👨🏽‍💻 man technologist: medium skin tone + 👨🏾‍💻 man technologist: medium-dark skin tone + 👨🏿‍💻 man technologist: dark skin tone + 👩‍💻 woman technologist + 👩🏻‍💻 woman technologist: light skin tone + 👩🏼‍💻 woman technologist: medium-light skin tone + 👩🏽‍💻 woman technologist: medium skin tone + 👩🏾‍💻 woman technologist: medium-dark skin tone + 👩🏿‍💻 woman technologist: dark skin tone + 🧑‍🎤 singer + 🧑🏻‍🎤 singer: light skin tone + 🧑🏼‍🎤 singer: medium-light skin tone + 🧑🏽‍🎤 singer: medium skin tone + 🧑🏾‍🎤 singer: medium-dark skin tone + 🧑🏿‍🎤 singer: dark skin tone + 👨‍🎤 man singer + 👨🏻‍🎤 man singer: light skin tone + 👨🏼‍🎤 man singer: medium-light skin tone + 👨🏽‍🎤 man singer: medium skin tone + 👨🏾‍🎤 man singer: medium-dark skin tone + 👨🏿‍🎤 man singer: dark skin tone + 👩‍🎤 woman singer + 👩🏻‍🎤 woman singer: light skin tone + 👩🏼‍🎤 woman singer: medium-light skin tone + 👩🏽‍🎤 woman singer: medium skin tone + 👩🏾‍🎤 woman singer: medium-dark skin tone + 👩🏿‍🎤 woman singer: dark skin tone + 🧑‍🎨 artist + 🧑🏻‍🎨 artist: light skin tone + 🧑🏼‍🎨 artist: medium-light skin tone + 🧑🏽‍🎨 artist: medium skin tone + 🧑🏾‍🎨 artist: medium-dark skin tone + 🧑🏿‍🎨 artist: dark skin tone + 👨‍🎨 man artist + 👨🏻‍🎨 man artist: light skin tone + 👨🏼‍🎨 man artist: medium-light skin tone + 👨🏽‍🎨 man artist: medium skin tone + 👨🏾‍🎨 man artist: medium-dark skin tone + 👨🏿‍🎨 man artist: dark skin tone + 👩‍🎨 woman artist + 👩🏻‍🎨 woman artist: light skin tone + 👩🏼‍🎨 woman artist: medium-light skin tone + 👩🏽‍🎨 woman artist: medium skin tone + 👩🏾‍🎨 woman artist: medium-dark skin tone + 👩🏿‍🎨 woman artist: dark skin tone + 🧑‍✈️ pilot + 🧑‍✈ pilot + 🧑🏻‍✈️ pilot: light skin tone + 🧑🏻‍✈ pilot: light skin tone + 🧑🏼‍✈️ pilot: medium-light skin tone + 🧑🏼‍✈ pilot: medium-light skin tone + 🧑🏽‍✈️ pilot: medium skin tone + 🧑🏽‍✈ pilot: medium skin tone + 🧑🏾‍✈️ pilot: medium-dark skin tone + 🧑🏾‍✈ pilot: medium-dark skin tone + 🧑🏿‍✈️ pilot: dark skin tone + 🧑🏿‍✈ pilot: dark skin tone + 👨‍✈️ man pilot + 👨‍✈ man pilot + 👨🏻‍✈️ man pilot: light skin tone + 👨🏻‍✈ man pilot: light skin tone + 👨🏼‍✈️ man pilot: medium-light skin tone + 👨🏼‍✈ man pilot: medium-light skin tone + 👨🏽‍✈️ man pilot: medium skin tone + 👨🏽‍✈ man pilot: medium skin tone + 👨🏾‍✈️ man pilot: medium-dark skin tone + 👨🏾‍✈ man pilot: medium-dark skin tone + 👨🏿‍✈️ man pilot: dark skin tone + 👨🏿‍✈ man pilot: dark skin tone + 👩‍✈️ woman pilot + 👩‍✈ woman pilot + 👩🏻‍✈️ woman pilot: light skin tone + 👩🏻‍✈ woman pilot: light skin tone + 👩🏼‍✈️ woman pilot: medium-light skin tone + 👩🏼‍✈ woman pilot: medium-light skin tone + 👩🏽‍✈️ woman pilot: medium skin tone + 👩🏽‍✈ woman pilot: medium skin tone + 👩🏾‍✈️ woman pilot: medium-dark skin tone + 👩🏾‍✈ woman pilot: medium-dark skin tone + 👩🏿‍✈️ woman pilot: dark skin tone + 👩🏿‍✈ woman pilot: dark skin tone + 🧑‍🚀 astronaut + 🧑🏻‍🚀 astronaut: light skin tone + 🧑🏼‍🚀 astronaut: medium-light skin tone + 🧑🏽‍🚀 astronaut: medium skin tone + 🧑🏾‍🚀 astronaut: medium-dark skin tone + 🧑🏿‍🚀 astronaut: dark skin tone + 👨‍🚀 man astronaut + 👨🏻‍🚀 man astronaut: light skin tone + 👨🏼‍🚀 man astronaut: medium-light skin tone + 👨🏽‍🚀 man astronaut: medium skin tone + 👨🏾‍🚀 man astronaut: medium-dark skin tone + 👨🏿‍🚀 man astronaut: dark skin tone + 👩‍🚀 woman astronaut + 👩🏻‍🚀 woman astronaut: light skin tone + 👩🏼‍🚀 woman astronaut: medium-light skin tone + 👩🏽‍🚀 woman astronaut: medium skin tone + 👩🏾‍🚀 woman astronaut: medium-dark skin tone + 👩🏿‍🚀 woman astronaut: dark skin tone + 🧑‍🚒 firefighter + 🧑🏻‍🚒 firefighter: light skin tone + 🧑🏼‍🚒 firefighter: medium-light skin tone + 🧑🏽‍🚒 firefighter: medium skin tone + 🧑🏾‍🚒 firefighter: medium-dark skin tone + 🧑🏿‍🚒 firefighter: dark skin tone + 👨‍🚒 man firefighter + 👨🏻‍🚒 man firefighter: light skin tone + 👨🏼‍🚒 man firefighter: medium-light skin tone + 👨🏽‍🚒 man firefighter: medium skin tone + 👨🏾‍🚒 man firefighter: medium-dark skin tone + 👨🏿‍🚒 man firefighter: dark skin tone + 👩‍🚒 woman firefighter + 👩🏻‍🚒 woman firefighter: light skin tone + 👩🏼‍🚒 woman firefighter: medium-light skin tone + 👩🏽‍🚒 woman firefighter: medium skin tone + 👩🏾‍🚒 woman firefighter: medium-dark skin tone + 👩🏿‍🚒 woman firefighter: dark skin tone + 👮 police officer + 👮🏻 police officer: light skin tone + 👮🏼 police officer: medium-light skin tone + 👮🏽 police officer: medium skin tone + 👮🏾 police officer: medium-dark skin tone + 👮🏿 police officer: dark skin tone + 👮‍♂️ man police officer + 👮‍♂ man police officer + 👮🏻‍♂️ man police officer: light skin tone + 👮🏻‍♂ man police officer: light skin tone + 👮🏼‍♂️ man police officer: medium-light skin tone + 👮🏼‍♂ man police officer: medium-light skin tone + 👮🏽‍♂️ man police officer: medium skin tone + 👮🏽‍♂ man police officer: medium skin tone + 👮🏾‍♂️ man police officer: medium-dark skin tone + 👮🏾‍♂ man police officer: medium-dark skin tone + 👮🏿‍♂️ man police officer: dark skin tone + 👮🏿‍♂ man police officer: dark skin tone + 👮‍♀️ woman police officer + 👮‍♀ woman police officer + 👮🏻‍♀️ woman police officer: light skin tone + 👮🏻‍♀ woman police officer: light skin tone + 👮🏼‍♀️ woman police officer: medium-light skin tone + 👮🏼‍♀ woman police officer: medium-light skin tone + 👮🏽‍♀️ woman police officer: medium skin tone + 👮🏽‍♀ woman police officer: medium skin tone + 👮🏾‍♀️ woman police officer: medium-dark skin tone + 👮🏾‍♀ woman police officer: medium-dark skin tone + 👮🏿‍♀️ woman police officer: dark skin tone + 👮🏿‍♀ woman police officer: dark skin tone + 🕵️ detective + 🕵 detective + 🕵🏻 detective: light skin tone + 🕵🏼 detective: medium-light skin tone + 🕵🏽 detective: medium skin tone + 🕵🏾 detective: medium-dark skin tone + 🕵🏿 detective: dark skin tone + 🕵️‍♂️ man detective + 🕵‍♂️ man detective + 🕵️‍♂ man detective + 🕵‍♂ man detective + 🕵🏻‍♂️ man detective: light skin tone + 🕵🏻‍♂ man detective: light skin tone + 🕵🏼‍♂️ man detective: medium-light skin tone + 🕵🏼‍♂ man detective: medium-light skin tone + 🕵🏽‍♂️ man detective: medium skin tone + 🕵🏽‍♂ man detective: medium skin tone + 🕵🏾‍♂️ man detective: medium-dark skin tone + 🕵🏾‍♂ man detective: medium-dark skin tone + 🕵🏿‍♂️ man detective: dark skin tone + 🕵🏿‍♂ man detective: dark skin tone + 🕵️‍♀️ woman detective + 🕵‍♀️ woman detective + 🕵️‍♀ woman detective + 🕵‍♀ woman detective + 🕵🏻‍♀️ woman detective: light skin tone + 🕵🏻‍♀ woman detective: light skin tone + 🕵🏼‍♀️ woman detective: medium-light skin tone + 🕵🏼‍♀ woman detective: medium-light skin tone + 🕵🏽‍♀️ woman detective: medium skin tone + 🕵🏽‍♀ woman detective: medium skin tone + 🕵🏾‍♀️ woman detective: medium-dark skin tone + 🕵🏾‍♀ woman detective: medium-dark skin tone + 🕵🏿‍♀️ woman detective: dark skin tone + 🕵🏿‍♀ woman detective: dark skin tone + 💂 guard + 💂🏻 guard: light skin tone + 💂🏼 guard: medium-light skin tone + 💂🏽 guard: medium skin tone + 💂🏾 guard: medium-dark skin tone + 💂🏿 guard: dark skin tone + 💂‍♂️ man guard + 💂‍♂ man guard + 💂🏻‍♂️ man guard: light skin tone + 💂🏻‍♂ man guard: light skin tone + 💂🏼‍♂️ man guard: medium-light skin tone + 💂🏼‍♂ man guard: medium-light skin tone + 💂🏽‍♂️ man guard: medium skin tone + 💂🏽‍♂ man guard: medium skin tone + 💂🏾‍♂️ man guard: medium-dark skin tone + 💂🏾‍♂ man guard: medium-dark skin tone + 💂🏿‍♂️ man guard: dark skin tone + 💂🏿‍♂ man guard: dark skin tone + 💂‍♀️ woman guard + 💂‍♀ woman guard + 💂🏻‍♀️ woman guard: light skin tone + 💂🏻‍♀ woman guard: light skin tone + 💂🏼‍♀️ woman guard: medium-light skin tone + 💂🏼‍♀ woman guard: medium-light skin tone + 💂🏽‍♀️ woman guard: medium skin tone + 💂🏽‍♀ woman guard: medium skin tone + 💂🏾‍♀️ woman guard: medium-dark skin tone + 💂🏾‍♀ woman guard: medium-dark skin tone + 💂🏿‍♀️ woman guard: dark skin tone + 💂🏿‍♀ woman guard: dark skin tone + 🥷 ninja + 🥷🏻 ninja: light skin tone + 🥷🏼 ninja: medium-light skin tone + 🥷🏽 ninja: medium skin tone + 🥷🏾 ninja: medium-dark skin tone + 🥷🏿 ninja: dark skin tone + 👷 construction worker + 👷🏻 construction worker: light skin tone + 👷🏼 construction worker: medium-light skin tone + 👷🏽 construction worker: medium skin tone + 👷🏾 construction worker: medium-dark skin tone + 👷🏿 construction worker: dark skin tone + 👷‍♂️ man construction worker + 👷‍♂ man construction worker + 👷🏻‍♂️ man construction worker: light skin tone + 👷🏻‍♂ man construction worker: light skin tone + 👷🏼‍♂️ man construction worker: medium-light skin tone + 👷🏼‍♂ man construction worker: medium-light skin tone + 👷🏽‍♂️ man construction worker: medium skin tone + 👷🏽‍♂ man construction worker: medium skin tone + 👷🏾‍♂️ man construction worker: medium-dark skin tone + 👷🏾‍♂ man construction worker: medium-dark skin tone + 👷🏿‍♂️ man construction worker: dark skin tone + 👷🏿‍♂ man construction worker: dark skin tone + 👷‍♀️ woman construction worker + 👷‍♀ woman construction worker + 👷🏻‍♀️ woman construction worker: light skin tone + 👷🏻‍♀ woman construction worker: light skin tone + 👷🏼‍♀️ woman construction worker: medium-light skin tone + 👷🏼‍♀ woman construction worker: medium-light skin tone + 👷🏽‍♀️ woman construction worker: medium skin tone + 👷🏽‍♀ woman construction worker: medium skin tone + 👷🏾‍♀️ woman construction worker: medium-dark skin tone + 👷🏾‍♀ woman construction worker: medium-dark skin tone + 👷🏿‍♀️ woman construction worker: dark skin tone + 👷🏿‍♀ woman construction worker: dark skin tone + 🫅 person with crown + 🫅🏻 person with crown: light skin tone + 🫅🏼 person with crown: medium-light skin tone + 🫅🏽 person with crown: medium skin tone + 🫅🏾 person with crown: medium-dark skin tone + 🫅🏿 person with crown: dark skin tone + 🤴 prince + 🤴🏻 prince: light skin tone + 🤴🏼 prince: medium-light skin tone + 🤴🏽 prince: medium skin tone + 🤴🏾 prince: medium-dark skin tone + 🤴🏿 prince: dark skin tone + 👸 princess + 👸🏻 princess: light skin tone + 👸🏼 princess: medium-light skin tone + 👸🏽 princess: medium skin tone + 👸🏾 princess: medium-dark skin tone + 👸🏿 princess: dark skin tone + 👳 person wearing turban + 👳🏻 person wearing turban: light skin tone + 👳🏼 person wearing turban: medium-light skin tone + 👳🏽 person wearing turban: medium skin tone + 👳🏾 person wearing turban: medium-dark skin tone + 👳🏿 person wearing turban: dark skin tone + 👳‍♂️ man wearing turban + 👳‍♂ man wearing turban + 👳🏻‍♂️ man wearing turban: light skin tone + 👳🏻‍♂ man wearing turban: light skin tone + 👳🏼‍♂️ man wearing turban: medium-light skin tone + 👳🏼‍♂ man wearing turban: medium-light skin tone + 👳🏽‍♂️ man wearing turban: medium skin tone + 👳🏽‍♂ man wearing turban: medium skin tone + 👳🏾‍♂️ man wearing turban: medium-dark skin tone + 👳🏾‍♂ man wearing turban: medium-dark skin tone + 👳🏿‍♂️ man wearing turban: dark skin tone + 👳🏿‍♂ man wearing turban: dark skin tone + 👳‍♀️ woman wearing turban + 👳‍♀ woman wearing turban + 👳🏻‍♀️ woman wearing turban: light skin tone + 👳🏻‍♀ woman wearing turban: light skin tone + 👳🏼‍♀️ woman wearing turban: medium-light skin tone + 👳🏼‍♀ woman wearing turban: medium-light skin tone + 👳🏽‍♀️ woman wearing turban: medium skin tone + 👳🏽‍♀ woman wearing turban: medium skin tone + 👳🏾‍♀️ woman wearing turban: medium-dark skin tone + 👳🏾‍♀ woman wearing turban: medium-dark skin tone + 👳🏿‍♀️ woman wearing turban: dark skin tone + 👳🏿‍♀ woman wearing turban: dark skin tone + 👲 person with skullcap + 👲🏻 person with skullcap: light skin tone + 👲🏼 person with skullcap: medium-light skin tone + 👲🏽 person with skullcap: medium skin tone + 👲🏾 person with skullcap: medium-dark skin tone + 👲🏿 person with skullcap: dark skin tone + 🧕 woman with headscarf + 🧕🏻 woman with headscarf: light skin tone + 🧕🏼 woman with headscarf: medium-light skin tone + 🧕🏽 woman with headscarf: medium skin tone + 🧕🏾 woman with headscarf: medium-dark skin tone + 🧕🏿 woman with headscarf: dark skin tone + 🤵 person in tuxedo + 🤵🏻 person in tuxedo: light skin tone + 🤵🏼 person in tuxedo: medium-light skin tone + 🤵🏽 person in tuxedo: medium skin tone + 🤵🏾 person in tuxedo: medium-dark skin tone + 🤵🏿 person in tuxedo: dark skin tone + 🤵‍♂️ man in tuxedo + 🤵‍♂ man in tuxedo + 🤵🏻‍♂️ man in tuxedo: light skin tone + 🤵🏻‍♂ man in tuxedo: light skin tone + 🤵🏼‍♂️ man in tuxedo: medium-light skin tone + 🤵🏼‍♂ man in tuxedo: medium-light skin tone + 🤵🏽‍♂️ man in tuxedo: medium skin tone + 🤵🏽‍♂ man in tuxedo: medium skin tone + 🤵🏾‍♂️ man in tuxedo: medium-dark skin tone + 🤵🏾‍♂ man in tuxedo: medium-dark skin tone + 🤵🏿‍♂️ man in tuxedo: dark skin tone + 🤵🏿‍♂ man in tuxedo: dark skin tone + 🤵‍♀️ woman in tuxedo + 🤵‍♀ woman in tuxedo + 🤵🏻‍♀️ woman in tuxedo: light skin tone + 🤵🏻‍♀ woman in tuxedo: light skin tone + 🤵🏼‍♀️ woman in tuxedo: medium-light skin tone + 🤵🏼‍♀ woman in tuxedo: medium-light skin tone + 🤵🏽‍♀️ woman in tuxedo: medium skin tone + 🤵🏽‍♀ woman in tuxedo: medium skin tone + 🤵🏾‍♀️ woman in tuxedo: medium-dark skin tone + 🤵🏾‍♀ woman in tuxedo: medium-dark skin tone + 🤵🏿‍♀️ woman in tuxedo: dark skin tone + 🤵🏿‍♀ woman in tuxedo: dark skin tone + 👰 person with veil + 👰🏻 person with veil: light skin tone + 👰🏼 person with veil: medium-light skin tone + 👰🏽 person with veil: medium skin tone + 👰🏾 person with veil: medium-dark skin tone + 👰🏿 person with veil: dark skin tone + 👰‍♂️ man with veil + 👰‍♂ man with veil + 👰🏻‍♂️ man with veil: light skin tone + 👰🏻‍♂ man with veil: light skin tone + 👰🏼‍♂️ man with veil: medium-light skin tone + 👰🏼‍♂ man with veil: medium-light skin tone + 👰🏽‍♂️ man with veil: medium skin tone + 👰🏽‍♂ man with veil: medium skin tone + 👰🏾‍♂️ man with veil: medium-dark skin tone + 👰🏾‍♂ man with veil: medium-dark skin tone + 👰🏿‍♂️ man with veil: dark skin tone + 👰🏿‍♂ man with veil: dark skin tone + 👰‍♀️ woman with veil + 👰‍♀ woman with veil + 👰🏻‍♀️ woman with veil: light skin tone + 👰🏻‍♀ woman with veil: light skin tone + 👰🏼‍♀️ woman with veil: medium-light skin tone + 👰🏼‍♀ woman with veil: medium-light skin tone + 👰🏽‍♀️ woman with veil: medium skin tone + 👰🏽‍♀ woman with veil: medium skin tone + 👰🏾‍♀️ woman with veil: medium-dark skin tone + 👰🏾‍♀ woman with veil: medium-dark skin tone + 👰🏿‍♀️ woman with veil: dark skin tone + 👰🏿‍♀ woman with veil: dark skin tone + 🤰 pregnant woman + 🤰🏻 pregnant woman: light skin tone + 🤰🏼 pregnant woman: medium-light skin tone + 🤰🏽 pregnant woman: medium skin tone + 🤰🏾 pregnant woman: medium-dark skin tone + 🤰🏿 pregnant woman: dark skin tone + 🫃 pregnant man + 🫃🏻 pregnant man: light skin tone + 🫃🏼 pregnant man: medium-light skin tone + 🫃🏽 pregnant man: medium skin tone + 🫃🏾 pregnant man: medium-dark skin tone + 🫃🏿 pregnant man: dark skin tone + 🫄 pregnant person + 🫄🏻 pregnant person: light skin tone + 🫄🏼 pregnant person: medium-light skin tone + 🫄🏽 pregnant person: medium skin tone + 🫄🏾 pregnant person: medium-dark skin tone + 🫄🏿 pregnant person: dark skin tone + 🤱 breast-feeding + 🤱🏻 breast-feeding: light skin tone + 🤱🏼 breast-feeding: medium-light skin tone + 🤱🏽 breast-feeding: medium skin tone + 🤱🏾 breast-feeding: medium-dark skin tone + 🤱🏿 breast-feeding: dark skin tone + 👩‍🍼 woman feeding baby + 👩🏻‍🍼 woman feeding baby: light skin tone + 👩🏼‍🍼 woman feeding baby: medium-light skin tone + 👩🏽‍🍼 woman feeding baby: medium skin tone + 👩🏾‍🍼 woman feeding baby: medium-dark skin tone + 👩🏿‍🍼 woman feeding baby: dark skin tone + 👨‍🍼 man feeding baby + 👨🏻‍🍼 man feeding baby: light skin tone + 👨🏼‍🍼 man feeding baby: medium-light skin tone + 👨🏽‍🍼 man feeding baby: medium skin tone + 👨🏾‍🍼 man feeding baby: medium-dark skin tone + 👨🏿‍🍼 man feeding baby: dark skin tone + 🧑‍🍼 person feeding baby + 🧑🏻‍🍼 person feeding baby: light skin tone + 🧑🏼‍🍼 person feeding baby: medium-light skin tone + 🧑🏽‍🍼 person feeding baby: medium skin tone + 🧑🏾‍🍼 person feeding baby: medium-dark skin tone + 🧑🏿‍🍼 person feeding baby: dark skin tone + 👼 baby angel + 👼🏻 baby angel: light skin tone + 👼🏼 baby angel: medium-light skin tone + 👼🏽 baby angel: medium skin tone + 👼🏾 baby angel: medium-dark skin tone + 👼🏿 baby angel: dark skin tone + 🎅 Santa Claus + 🎅🏻 Santa Claus: light skin tone + 🎅🏼 Santa Claus: medium-light skin tone + 🎅🏽 Santa Claus: medium skin tone + 🎅🏾 Santa Claus: medium-dark skin tone + 🎅🏿 Santa Claus: dark skin tone + 🤶 Mrs. Claus + 🤶🏻 Mrs. Claus: light skin tone + 🤶🏼 Mrs. Claus: medium-light skin tone + 🤶🏽 Mrs. Claus: medium skin tone + 🤶🏾 Mrs. Claus: medium-dark skin tone + 🤶🏿 Mrs. Claus: dark skin tone + 🧑‍🎄 mx claus + 🧑🏻‍🎄 mx claus: light skin tone + 🧑🏼‍🎄 mx claus: medium-light skin tone + 🧑🏽‍🎄 mx claus: medium skin tone + 🧑🏾‍🎄 mx claus: medium-dark skin tone + 🧑🏿‍🎄 mx claus: dark skin tone + 🦸 superhero + 🦸🏻 superhero: light skin tone + 🦸🏼 superhero: medium-light skin tone + 🦸🏽 superhero: medium skin tone + 🦸🏾 superhero: medium-dark skin tone + 🦸🏿 superhero: dark skin tone + 🦸‍♂️ man superhero + 🦸‍♂ man superhero + 🦸🏻‍♂️ man superhero: light skin tone + 🦸🏻‍♂ man superhero: light skin tone + 🦸🏼‍♂️ man superhero: medium-light skin tone + 🦸🏼‍♂ man superhero: medium-light skin tone + 🦸🏽‍♂️ man superhero: medium skin tone + 🦸🏽‍♂ man superhero: medium skin tone + 🦸🏾‍♂️ man superhero: medium-dark skin tone + 🦸🏾‍♂ man superhero: medium-dark skin tone + 🦸🏿‍♂️ man superhero: dark skin tone + 🦸🏿‍♂ man superhero: dark skin tone + 🦸‍♀️ woman superhero + 🦸‍♀ woman superhero + 🦸🏻‍♀️ woman superhero: light skin tone + 🦸🏻‍♀ woman superhero: light skin tone + 🦸🏼‍♀️ woman superhero: medium-light skin tone + 🦸🏼‍♀ woman superhero: medium-light skin tone + 🦸🏽‍♀️ woman superhero: medium skin tone + 🦸🏽‍♀ woman superhero: medium skin tone + 🦸🏾‍♀️ woman superhero: medium-dark skin tone + 🦸🏾‍♀ woman superhero: medium-dark skin tone + 🦸🏿‍♀️ woman superhero: dark skin tone + 🦸🏿‍♀ woman superhero: dark skin tone + 🦹 supervillain + 🦹🏻 supervillain: light skin tone + 🦹🏼 supervillain: medium-light skin tone + 🦹🏽 supervillain: medium skin tone + 🦹🏾 supervillain: medium-dark skin tone + 🦹🏿 supervillain: dark skin tone + 🦹‍♂️ man supervillain + 🦹‍♂ man supervillain + 🦹🏻‍♂️ man supervillain: light skin tone + 🦹🏻‍♂ man supervillain: light skin tone + 🦹🏼‍♂️ man supervillain: medium-light skin tone + 🦹🏼‍♂ man supervillain: medium-light skin tone + 🦹🏽‍♂️ man supervillain: medium skin tone + 🦹🏽‍♂ man supervillain: medium skin tone + 🦹🏾‍♂️ man supervillain: medium-dark skin tone + 🦹🏾‍♂ man supervillain: medium-dark skin tone + 🦹🏿‍♂️ man supervillain: dark skin tone + 🦹🏿‍♂ man supervillain: dark skin tone + 🦹‍♀️ woman supervillain + 🦹‍♀ woman supervillain + 🦹🏻‍♀️ woman supervillain: light skin tone + 🦹🏻‍♀ woman supervillain: light skin tone + 🦹🏼‍♀️ woman supervillain: medium-light skin tone + 🦹🏼‍♀ woman supervillain: medium-light skin tone + 🦹🏽‍♀️ woman supervillain: medium skin tone + 🦹🏽‍♀ woman supervillain: medium skin tone + 🦹🏾‍♀️ woman supervillain: medium-dark skin tone + 🦹🏾‍♀ woman supervillain: medium-dark skin tone + 🦹🏿‍♀️ woman supervillain: dark skin tone + 🦹🏿‍♀ woman supervillain: dark skin tone + 🧙 mage + 🧙🏻 mage: light skin tone + 🧙🏼 mage: medium-light skin tone + 🧙🏽 mage: medium skin tone + 🧙🏾 mage: medium-dark skin tone + 🧙🏿 mage: dark skin tone + 🧙‍♂️ man mage + 🧙‍♂ man mage + 🧙🏻‍♂️ man mage: light skin tone + 🧙🏻‍♂ man mage: light skin tone + 🧙🏼‍♂️ man mage: medium-light skin tone + 🧙🏼‍♂ man mage: medium-light skin tone + 🧙🏽‍♂️ man mage: medium skin tone + 🧙🏽‍♂ man mage: medium skin tone + 🧙🏾‍♂️ man mage: medium-dark skin tone + 🧙🏾‍♂ man mage: medium-dark skin tone + 🧙🏿‍♂️ man mage: dark skin tone + 🧙🏿‍♂ man mage: dark skin tone + 🧙‍♀️ woman mage + 🧙‍♀ woman mage + 🧙🏻‍♀️ woman mage: light skin tone + 🧙🏻‍♀ woman mage: light skin tone + 🧙🏼‍♀️ woman mage: medium-light skin tone + 🧙🏼‍♀ woman mage: medium-light skin tone + 🧙🏽‍♀️ woman mage: medium skin tone + 🧙🏽‍♀ woman mage: medium skin tone + 🧙🏾‍♀️ woman mage: medium-dark skin tone + 🧙🏾‍♀ woman mage: medium-dark skin tone + 🧙🏿‍♀️ woman mage: dark skin tone + 🧙🏿‍♀ woman mage: dark skin tone + 🧚 fairy + 🧚🏻 fairy: light skin tone + 🧚🏼 fairy: medium-light skin tone + 🧚🏽 fairy: medium skin tone + 🧚🏾 fairy: medium-dark skin tone + 🧚🏿 fairy: dark skin tone + 🧚‍♂️ man fairy + 🧚‍♂ man fairy + 🧚🏻‍♂️ man fairy: light skin tone + 🧚🏻‍♂ man fairy: light skin tone + 🧚🏼‍♂️ man fairy: medium-light skin tone + 🧚🏼‍♂ man fairy: medium-light skin tone + 🧚🏽‍♂️ man fairy: medium skin tone + 🧚🏽‍♂ man fairy: medium skin tone + 🧚🏾‍♂️ man fairy: medium-dark skin tone + 🧚🏾‍♂ man fairy: medium-dark skin tone + 🧚🏿‍♂️ man fairy: dark skin tone + 🧚🏿‍♂ man fairy: dark skin tone + 🧚‍♀️ woman fairy + 🧚‍♀ woman fairy + 🧚🏻‍♀️ woman fairy: light skin tone + 🧚🏻‍♀ woman fairy: light skin tone + 🧚🏼‍♀️ woman fairy: medium-light skin tone + 🧚🏼‍♀ woman fairy: medium-light skin tone + 🧚🏽‍♀️ woman fairy: medium skin tone + 🧚🏽‍♀ woman fairy: medium skin tone + 🧚🏾‍♀️ woman fairy: medium-dark skin tone + 🧚🏾‍♀ woman fairy: medium-dark skin tone + 🧚🏿‍♀️ woman fairy: dark skin tone + 🧚🏿‍♀ woman fairy: dark skin tone + 🧛 vampire + 🧛🏻 vampire: light skin tone + 🧛🏼 vampire: medium-light skin tone + 🧛🏽 vampire: medium skin tone + 🧛🏾 vampire: medium-dark skin tone + 🧛🏿 vampire: dark skin tone + 🧛‍♂️ man vampire + 🧛‍♂ man vampire + 🧛🏻‍♂️ man vampire: light skin tone + 🧛🏻‍♂ man vampire: light skin tone + 🧛🏼‍♂️ man vampire: medium-light skin tone + 🧛🏼‍♂ man vampire: medium-light skin tone + 🧛🏽‍♂️ man vampire: medium skin tone + 🧛🏽‍♂ man vampire: medium skin tone + 🧛🏾‍♂️ man vampire: medium-dark skin tone + 🧛🏾‍♂ man vampire: medium-dark skin tone + 🧛🏿‍♂️ man vampire: dark skin tone + 🧛🏿‍♂ man vampire: dark skin tone + 🧛‍♀️ woman vampire + 🧛‍♀ woman vampire + 🧛🏻‍♀️ woman vampire: light skin tone + 🧛🏻‍♀ woman vampire: light skin tone + 🧛🏼‍♀️ woman vampire: medium-light skin tone + 🧛🏼‍♀ woman vampire: medium-light skin tone + 🧛🏽‍♀️ woman vampire: medium skin tone + 🧛🏽‍♀ woman vampire: medium skin tone + 🧛🏾‍♀️ woman vampire: medium-dark skin tone + 🧛🏾‍♀ woman vampire: medium-dark skin tone + 🧛🏿‍♀️ woman vampire: dark skin tone + 🧛🏿‍♀ woman vampire: dark skin tone + 🧜 merperson + 🧜🏻 merperson: light skin tone + 🧜🏼 merperson: medium-light skin tone + 🧜🏽 merperson: medium skin tone + 🧜🏾 merperson: medium-dark skin tone + 🧜🏿 merperson: dark skin tone + 🧜‍♂️ merman + 🧜‍♂ merman + 🧜🏻‍♂️ merman: light skin tone + 🧜🏻‍♂ merman: light skin tone + 🧜🏼‍♂️ merman: medium-light skin tone + 🧜🏼‍♂ merman: medium-light skin tone + 🧜🏽‍♂️ merman: medium skin tone + 🧜🏽‍♂ merman: medium skin tone + 🧜🏾‍♂️ merman: medium-dark skin tone + 🧜🏾‍♂ merman: medium-dark skin tone + 🧜🏿‍♂️ merman: dark skin tone + 🧜🏿‍♂ merman: dark skin tone + 🧜‍♀️ mermaid + 🧜‍♀ mermaid + 🧜🏻‍♀️ mermaid: light skin tone + 🧜🏻‍♀ mermaid: light skin tone + 🧜🏼‍♀️ mermaid: medium-light skin tone + 🧜🏼‍♀ mermaid: medium-light skin tone + 🧜🏽‍♀️ mermaid: medium skin tone + 🧜🏽‍♀ mermaid: medium skin tone + 🧜🏾‍♀️ mermaid: medium-dark skin tone + 🧜🏾‍♀ mermaid: medium-dark skin tone + 🧜🏿‍♀️ mermaid: dark skin tone + 🧜🏿‍♀ mermaid: dark skin tone + 🧝 elf + 🧝🏻 elf: light skin tone + 🧝🏼 elf: medium-light skin tone + 🧝🏽 elf: medium skin tone + 🧝🏾 elf: medium-dark skin tone + 🧝🏿 elf: dark skin tone + 🧝‍♂️ man elf + 🧝‍♂ man elf + 🧝🏻‍♂️ man elf: light skin tone + 🧝🏻‍♂ man elf: light skin tone + 🧝🏼‍♂️ man elf: medium-light skin tone + 🧝🏼‍♂ man elf: medium-light skin tone + 🧝🏽‍♂️ man elf: medium skin tone + 🧝🏽‍♂ man elf: medium skin tone + 🧝🏾‍♂️ man elf: medium-dark skin tone + 🧝🏾‍♂ man elf: medium-dark skin tone + 🧝🏿‍♂️ man elf: dark skin tone + 🧝🏿‍♂ man elf: dark skin tone + 🧝‍♀️ woman elf + 🧝‍♀ woman elf + 🧝🏻‍♀️ woman elf: light skin tone + 🧝🏻‍♀ woman elf: light skin tone + 🧝🏼‍♀️ woman elf: medium-light skin tone + 🧝🏼‍♀ woman elf: medium-light skin tone + 🧝🏽‍♀️ woman elf: medium skin tone + 🧝🏽‍♀ woman elf: medium skin tone + 🧝🏾‍♀️ woman elf: medium-dark skin tone + 🧝🏾‍♀ woman elf: medium-dark skin tone + 🧝🏿‍♀️ woman elf: dark skin tone + 🧝🏿‍♀ woman elf: dark skin tone + 🧞 genie + 🧞‍♂️ man genie + 🧞‍♂ man genie + 🧞‍♀️ woman genie + 🧞‍♀ woman genie + 🧟 zombie + 🧟‍♂️ man zombie + 🧟‍♂ man zombie + 🧟‍♀️ woman zombie + 🧟‍♀ woman zombie + 🧌 troll + 💆 person getting massage + 💆🏻 person getting massage: light skin tone + 💆🏼 person getting massage: medium-light skin tone + 💆🏽 person getting massage: medium skin tone + 💆🏾 person getting massage: medium-dark skin tone + 💆🏿 person getting massage: dark skin tone + 💆‍♂️ man getting massage + 💆‍♂ man getting massage + 💆🏻‍♂️ man getting massage: light skin tone + 💆🏻‍♂ man getting massage: light skin tone + 💆🏼‍♂️ man getting massage: medium-light skin tone + 💆🏼‍♂ man getting massage: medium-light skin tone + 💆🏽‍♂️ man getting massage: medium skin tone + 💆🏽‍♂ man getting massage: medium skin tone + 💆🏾‍♂️ man getting massage: medium-dark skin tone + 💆🏾‍♂ man getting massage: medium-dark skin tone + 💆🏿‍♂️ man getting massage: dark skin tone + 💆🏿‍♂ man getting massage: dark skin tone + 💆‍♀️ woman getting massage + 💆‍♀ woman getting massage + 💆🏻‍♀️ woman getting massage: light skin tone + 💆🏻‍♀ woman getting massage: light skin tone + 💆🏼‍♀️ woman getting massage: medium-light skin tone + 💆🏼‍♀ woman getting massage: medium-light skin tone + 💆🏽‍♀️ woman getting massage: medium skin tone + 💆🏽‍♀ woman getting massage: medium skin tone + 💆🏾‍♀️ woman getting massage: medium-dark skin tone + 💆🏾‍♀ woman getting massage: medium-dark skin tone + 💆🏿‍♀️ woman getting massage: dark skin tone + 💆🏿‍♀ woman getting massage: dark skin tone + 💇 person getting haircut + 💇🏻 person getting haircut: light skin tone + 💇🏼 person getting haircut: medium-light skin tone + 💇🏽 person getting haircut: medium skin tone + 💇🏾 person getting haircut: medium-dark skin tone + 💇🏿 person getting haircut: dark skin tone + 💇‍♂️ man getting haircut + 💇‍♂ man getting haircut + 💇🏻‍♂️ man getting haircut: light skin tone + 💇🏻‍♂ man getting haircut: light skin tone + 💇🏼‍♂️ man getting haircut: medium-light skin tone + 💇🏼‍♂ man getting haircut: medium-light skin tone + 💇🏽‍♂️ man getting haircut: medium skin tone + 💇🏽‍♂ man getting haircut: medium skin tone + 💇🏾‍♂️ man getting haircut: medium-dark skin tone + 💇🏾‍♂ man getting haircut: medium-dark skin tone + 💇🏿‍♂️ man getting haircut: dark skin tone + 💇🏿‍♂ man getting haircut: dark skin tone + 💇‍♀️ woman getting haircut + 💇‍♀ woman getting haircut + 💇🏻‍♀️ woman getting haircut: light skin tone + 💇🏻‍♀ woman getting haircut: light skin tone + 💇🏼‍♀️ woman getting haircut: medium-light skin tone + 💇🏼‍♀ woman getting haircut: medium-light skin tone + 💇🏽‍♀️ woman getting haircut: medium skin tone + 💇🏽‍♀ woman getting haircut: medium skin tone + 💇🏾‍♀️ woman getting haircut: medium-dark skin tone + 💇🏾‍♀ woman getting haircut: medium-dark skin tone + 💇🏿‍♀️ woman getting haircut: dark skin tone + 💇🏿‍♀ woman getting haircut: dark skin tone + 🚶 person walking + 🚶🏻 person walking: light skin tone + 🚶🏼 person walking: medium-light skin tone + 🚶🏽 person walking: medium skin tone + 🚶🏾 person walking: medium-dark skin tone + 🚶🏿 person walking: dark skin tone + 🚶‍♂️ man walking + 🚶‍♂ man walking + 🚶🏻‍♂️ man walking: light skin tone + 🚶🏻‍♂ man walking: light skin tone + 🚶🏼‍♂️ man walking: medium-light skin tone + 🚶🏼‍♂ man walking: medium-light skin tone + 🚶🏽‍♂️ man walking: medium skin tone + 🚶🏽‍♂ man walking: medium skin tone + 🚶🏾‍♂️ man walking: medium-dark skin tone + 🚶🏾‍♂ man walking: medium-dark skin tone + 🚶🏿‍♂️ man walking: dark skin tone + 🚶🏿‍♂ man walking: dark skin tone + 🚶‍♀️ woman walking + 🚶‍♀ woman walking + 🚶🏻‍♀️ woman walking: light skin tone + 🚶🏻‍♀ woman walking: light skin tone + 🚶🏼‍♀️ woman walking: medium-light skin tone + 🚶🏼‍♀ woman walking: medium-light skin tone + 🚶🏽‍♀️ woman walking: medium skin tone + 🚶🏽‍♀ woman walking: medium skin tone + 🚶🏾‍♀️ woman walking: medium-dark skin tone + 🚶🏾‍♀ woman walking: medium-dark skin tone + 🚶🏿‍♀️ woman walking: dark skin tone + 🚶🏿‍♀ woman walking: dark skin tone + 🧍 person standing + 🧍🏻 person standing: light skin tone + 🧍🏼 person standing: medium-light skin tone + 🧍🏽 person standing: medium skin tone + 🧍🏾 person standing: medium-dark skin tone + 🧍🏿 person standing: dark skin tone + 🧍‍♂️ man standing + 🧍‍♂ man standing + 🧍🏻‍♂️ man standing: light skin tone + 🧍🏻‍♂ man standing: light skin tone + 🧍🏼‍♂️ man standing: medium-light skin tone + 🧍🏼‍♂ man standing: medium-light skin tone + 🧍🏽‍♂️ man standing: medium skin tone + 🧍🏽‍♂ man standing: medium skin tone + 🧍🏾‍♂️ man standing: medium-dark skin tone + 🧍🏾‍♂ man standing: medium-dark skin tone + 🧍🏿‍♂️ man standing: dark skin tone + 🧍🏿‍♂ man standing: dark skin tone + 🧍‍♀️ woman standing + 🧍‍♀ woman standing + 🧍🏻‍♀️ woman standing: light skin tone + 🧍🏻‍♀ woman standing: light skin tone + 🧍🏼‍♀️ woman standing: medium-light skin tone + 🧍🏼‍♀ woman standing: medium-light skin tone + 🧍🏽‍♀️ woman standing: medium skin tone + 🧍🏽‍♀ woman standing: medium skin tone + 🧍🏾‍♀️ woman standing: medium-dark skin tone + 🧍🏾‍♀ woman standing: medium-dark skin tone + 🧍🏿‍♀️ woman standing: dark skin tone + 🧍🏿‍♀ woman standing: dark skin tone + 🧎 person kneeling + 🧎🏻 person kneeling: light skin tone + 🧎🏼 person kneeling: medium-light skin tone + 🧎🏽 person kneeling: medium skin tone + 🧎🏾 person kneeling: medium-dark skin tone + 🧎🏿 person kneeling: dark skin tone + 🧎‍♂️ man kneeling + 🧎‍♂ man kneeling + 🧎🏻‍♂️ man kneeling: light skin tone + 🧎🏻‍♂ man kneeling: light skin tone + 🧎🏼‍♂️ man kneeling: medium-light skin tone + 🧎🏼‍♂ man kneeling: medium-light skin tone + 🧎🏽‍♂️ man kneeling: medium skin tone + 🧎🏽‍♂ man kneeling: medium skin tone + 🧎🏾‍♂️ man kneeling: medium-dark skin tone + 🧎🏾‍♂ man kneeling: medium-dark skin tone + 🧎🏿‍♂️ man kneeling: dark skin tone + 🧎🏿‍♂ man kneeling: dark skin tone + 🧎‍♀️ woman kneeling + 🧎‍♀ woman kneeling + 🧎🏻‍♀️ woman kneeling: light skin tone + 🧎🏻‍♀ woman kneeling: light skin tone + 🧎🏼‍♀️ woman kneeling: medium-light skin tone + 🧎🏼‍♀ woman kneeling: medium-light skin tone + 🧎🏽‍♀️ woman kneeling: medium skin tone + 🧎🏽‍♀ woman kneeling: medium skin tone + 🧎🏾‍♀️ woman kneeling: medium-dark skin tone + 🧎🏾‍♀ woman kneeling: medium-dark skin tone + 🧎🏿‍♀️ woman kneeling: dark skin tone + 🧎🏿‍♀ woman kneeling: dark skin tone + 🧑‍🦯 person with white cane + 🧑🏻‍🦯 person with white cane: light skin tone + 🧑🏼‍🦯 person with white cane: medium-light skin tone + 🧑🏽‍🦯 person with white cane: medium skin tone + 🧑🏾‍🦯 person with white cane: medium-dark skin tone + 🧑🏿‍🦯 person with white cane: dark skin tone + 👨‍🦯 man with white cane + 👨🏻‍🦯 man with white cane: light skin tone + 👨🏼‍🦯 man with white cane: medium-light skin tone + 👨🏽‍🦯 man with white cane: medium skin tone + 👨🏾‍🦯 man with white cane: medium-dark skin tone + 👨🏿‍🦯 man with white cane: dark skin tone + 👩‍🦯 woman with white cane + 👩🏻‍🦯 woman with white cane: light skin tone + 👩🏼‍🦯 woman with white cane: medium-light skin tone + 👩🏽‍🦯 woman with white cane: medium skin tone + 👩🏾‍🦯 woman with white cane: medium-dark skin tone + 👩🏿‍🦯 woman with white cane: dark skin tone + 🧑‍🦼 person in motorized wheelchair + 🧑🏻‍🦼 person in motorized wheelchair: light skin tone + 🧑🏼‍🦼 person in motorized wheelchair: medium-light skin tone + 🧑🏽‍🦼 person in motorized wheelchair: medium skin tone + 🧑🏾‍🦼 person in motorized wheelchair: medium-dark skin tone + 🧑🏿‍🦼 person in motorized wheelchair: dark skin tone + 👨‍🦼 man in motorized wheelchair + 👨🏻‍🦼 man in motorized wheelchair: light skin tone + 👨🏼‍🦼 man in motorized wheelchair: medium-light skin tone + 👨🏽‍🦼 man in motorized wheelchair: medium skin tone + 👨🏾‍🦼 man in motorized wheelchair: medium-dark skin tone + 👨🏿‍🦼 man in motorized wheelchair: dark skin tone + 👩‍🦼 woman in motorized wheelchair + 👩🏻‍🦼 woman in motorized wheelchair: light skin tone + 👩🏼‍🦼 woman in motorized wheelchair: medium-light skin tone + 👩🏽‍🦼 woman in motorized wheelchair: medium skin tone + 👩🏾‍🦼 woman in motorized wheelchair: medium-dark skin tone + 👩🏿‍🦼 woman in motorized wheelchair: dark skin tone + 🧑‍🦽 person in manual wheelchair + 🧑🏻‍🦽 person in manual wheelchair: light skin tone + 🧑🏼‍🦽 person in manual wheelchair: medium-light skin tone + 🧑🏽‍🦽 person in manual wheelchair: medium skin tone + 🧑🏾‍🦽 person in manual wheelchair: medium-dark skin tone + 🧑🏿‍🦽 person in manual wheelchair: dark skin tone + 👨‍🦽 man in manual wheelchair + 👨🏻‍🦽 man in manual wheelchair: light skin tone + 👨🏼‍🦽 man in manual wheelchair: medium-light skin tone + 👨🏽‍🦽 man in manual wheelchair: medium skin tone + 👨🏾‍🦽 man in manual wheelchair: medium-dark skin tone + 👨🏿‍🦽 man in manual wheelchair: dark skin tone + 👩‍🦽 woman in manual wheelchair + 👩🏻‍🦽 woman in manual wheelchair: light skin tone + 👩🏼‍🦽 woman in manual wheelchair: medium-light skin tone + 👩🏽‍🦽 woman in manual wheelchair: medium skin tone + 👩🏾‍🦽 woman in manual wheelchair: medium-dark skin tone + 👩🏿‍🦽 woman in manual wheelchair: dark skin tone + 🏃 person running + 🏃🏻 person running: light skin tone + 🏃🏼 person running: medium-light skin tone + 🏃🏽 person running: medium skin tone + 🏃🏾 person running: medium-dark skin tone + 🏃🏿 person running: dark skin tone + 🏃‍♂️ man running + 🏃‍♂ man running + 🏃🏻‍♂️ man running: light skin tone + 🏃🏻‍♂ man running: light skin tone + 🏃🏼‍♂️ man running: medium-light skin tone + 🏃🏼‍♂ man running: medium-light skin tone + 🏃🏽‍♂️ man running: medium skin tone + 🏃🏽‍♂ man running: medium skin tone + 🏃🏾‍♂️ man running: medium-dark skin tone + 🏃🏾‍♂ man running: medium-dark skin tone + 🏃🏿‍♂️ man running: dark skin tone + 🏃🏿‍♂ man running: dark skin tone + 🏃‍♀️ woman running + 🏃‍♀ woman running + 🏃🏻‍♀️ woman running: light skin tone + 🏃🏻‍♀ woman running: light skin tone + 🏃🏼‍♀️ woman running: medium-light skin tone + 🏃🏼‍♀ woman running: medium-light skin tone + 🏃🏽‍♀️ woman running: medium skin tone + 🏃🏽‍♀ woman running: medium skin tone + 🏃🏾‍♀️ woman running: medium-dark skin tone + 🏃🏾‍♀ woman running: medium-dark skin tone + 🏃🏿‍♀️ woman running: dark skin tone + 🏃🏿‍♀ woman running: dark skin tone + 💃 woman dancing + 💃🏻 woman dancing: light skin tone + 💃🏼 woman dancing: medium-light skin tone + 💃🏽 woman dancing: medium skin tone + 💃🏾 woman dancing: medium-dark skin tone + 💃🏿 woman dancing: dark skin tone + 🕺 man dancing + 🕺🏻 man dancing: light skin tone + 🕺🏼 man dancing: medium-light skin tone + 🕺🏽 man dancing: medium skin tone + 🕺🏾 man dancing: medium-dark skin tone + 🕺🏿 man dancing: dark skin tone + 🕴️ person in suit levitating + 🕴 person in suit levitating + 🕴🏻 person in suit levitating: light skin tone + 🕴🏼 person in suit levitating: medium-light skin tone + 🕴🏽 person in suit levitating: medium skin tone + 🕴🏾 person in suit levitating: medium-dark skin tone + 🕴🏿 person in suit levitating: dark skin tone + 👯 people with bunny ears + 👯‍♂️ men with bunny ears + 👯‍♂ men with bunny ears + 👯‍♀️ women with bunny ears + 👯‍♀ women with bunny ears + 🧖 person in steamy room + 🧖🏻 person in steamy room: light skin tone + 🧖🏼 person in steamy room: medium-light skin tone + 🧖🏽 person in steamy room: medium skin tone + 🧖🏾 person in steamy room: medium-dark skin tone + 🧖🏿 person in steamy room: dark skin tone + 🧖‍♂️ man in steamy room + 🧖‍♂ man in steamy room + 🧖🏻‍♂️ man in steamy room: light skin tone + 🧖🏻‍♂ man in steamy room: light skin tone + 🧖🏼‍♂️ man in steamy room: medium-light skin tone + 🧖🏼‍♂ man in steamy room: medium-light skin tone + 🧖🏽‍♂️ man in steamy room: medium skin tone + 🧖🏽‍♂ man in steamy room: medium skin tone + 🧖🏾‍♂️ man in steamy room: medium-dark skin tone + 🧖🏾‍♂ man in steamy room: medium-dark skin tone + 🧖🏿‍♂️ man in steamy room: dark skin tone + 🧖🏿‍♂ man in steamy room: dark skin tone + 🧖‍♀️ woman in steamy room + 🧖‍♀ woman in steamy room + 🧖🏻‍♀️ woman in steamy room: light skin tone + 🧖🏻‍♀ woman in steamy room: light skin tone + 🧖🏼‍♀️ woman in steamy room: medium-light skin tone + 🧖🏼‍♀ woman in steamy room: medium-light skin tone + 🧖🏽‍♀️ woman in steamy room: medium skin tone + 🧖🏽‍♀ woman in steamy room: medium skin tone + 🧖🏾‍♀️ woman in steamy room: medium-dark skin tone + 🧖🏾‍♀ woman in steamy room: medium-dark skin tone + 🧖🏿‍♀️ woman in steamy room: dark skin tone + 🧖🏿‍♀ woman in steamy room: dark skin tone + 🧗 person climbing + 🧗🏻 person climbing: light skin tone + 🧗🏼 person climbing: medium-light skin tone + 🧗🏽 person climbing: medium skin tone + 🧗🏾 person climbing: medium-dark skin tone + 🧗🏿 person climbing: dark skin tone + 🧗‍♂️ man climbing + 🧗‍♂ man climbing + 🧗🏻‍♂️ man climbing: light skin tone + 🧗🏻‍♂ man climbing: light skin tone + 🧗🏼‍♂️ man climbing: medium-light skin tone + 🧗🏼‍♂ man climbing: medium-light skin tone + 🧗🏽‍♂️ man climbing: medium skin tone + 🧗🏽‍♂ man climbing: medium skin tone + 🧗🏾‍♂️ man climbing: medium-dark skin tone + 🧗🏾‍♂ man climbing: medium-dark skin tone + 🧗🏿‍♂️ man climbing: dark skin tone + 🧗🏿‍♂ man climbing: dark skin tone + 🧗‍♀️ woman climbing + 🧗‍♀ woman climbing + 🧗🏻‍♀️ woman climbing: light skin tone + 🧗🏻‍♀ woman climbing: light skin tone + 🧗🏼‍♀️ woman climbing: medium-light skin tone + 🧗🏼‍♀ woman climbing: medium-light skin tone + 🧗🏽‍♀️ woman climbing: medium skin tone + 🧗🏽‍♀ woman climbing: medium skin tone + 🧗🏾‍♀️ woman climbing: medium-dark skin tone + 🧗🏾‍♀ woman climbing: medium-dark skin tone + 🧗🏿‍♀️ woman climbing: dark skin tone + 🧗🏿‍♀ woman climbing: dark skin tone + 🤺 person fencing + 🏇 horse racing + 🏇🏻 horse racing: light skin tone + 🏇🏼 horse racing: medium-light skin tone + 🏇🏽 horse racing: medium skin tone + 🏇🏾 horse racing: medium-dark skin tone + 🏇🏿 horse racing: dark skin tone + ⛷️ skier + ⛷ skier + 🏂 snowboarder + 🏂🏻 snowboarder: light skin tone + 🏂🏼 snowboarder: medium-light skin tone + 🏂🏽 snowboarder: medium skin tone + 🏂🏾 snowboarder: medium-dark skin tone + 🏂🏿 snowboarder: dark skin tone + 🏌️ person golfing + 🏌 person golfing + 🏌🏻 person golfing: light skin tone + 🏌🏼 person golfing: medium-light skin tone + 🏌🏽 person golfing: medium skin tone + 🏌🏾 person golfing: medium-dark skin tone + 🏌🏿 person golfing: dark skin tone + 🏌️‍♂️ man golfing + 🏌‍♂️ man golfing + 🏌️‍♂ man golfing + 🏌‍♂ man golfing + 🏌🏻‍♂️ man golfing: light skin tone + 🏌🏻‍♂ man golfing: light skin tone + 🏌🏼‍♂️ man golfing: medium-light skin tone + 🏌🏼‍♂ man golfing: medium-light skin tone + 🏌🏽‍♂️ man golfing: medium skin tone + 🏌🏽‍♂ man golfing: medium skin tone + 🏌🏾‍♂️ man golfing: medium-dark skin tone + 🏌🏾‍♂ man golfing: medium-dark skin tone + 🏌🏿‍♂️ man golfing: dark skin tone + 🏌🏿‍♂ man golfing: dark skin tone + 🏌️‍♀️ woman golfing + 🏌‍♀️ woman golfing + 🏌️‍♀ woman golfing + 🏌‍♀ woman golfing + 🏌🏻‍♀️ woman golfing: light skin tone + 🏌🏻‍♀ woman golfing: light skin tone + 🏌🏼‍♀️ woman golfing: medium-light skin tone + 🏌🏼‍♀ woman golfing: medium-light skin tone + 🏌🏽‍♀️ woman golfing: medium skin tone + 🏌🏽‍♀ woman golfing: medium skin tone + 🏌🏾‍♀️ woman golfing: medium-dark skin tone + 🏌🏾‍♀ woman golfing: medium-dark skin tone + 🏌🏿‍♀️ woman golfing: dark skin tone + 🏌🏿‍♀ woman golfing: dark skin tone + 🏄 person surfing + 🏄🏻 person surfing: light skin tone + 🏄🏼 person surfing: medium-light skin tone + 🏄🏽 person surfing: medium skin tone + 🏄🏾 person surfing: medium-dark skin tone + 🏄🏿 person surfing: dark skin tone + 🏄‍♂️ man surfing + 🏄‍♂ man surfing + 🏄🏻‍♂️ man surfing: light skin tone + 🏄🏻‍♂ man surfing: light skin tone + 🏄🏼‍♂️ man surfing: medium-light skin tone + 🏄🏼‍♂ man surfing: medium-light skin tone + 🏄🏽‍♂️ man surfing: medium skin tone + 🏄🏽‍♂ man surfing: medium skin tone + 🏄🏾‍♂️ man surfing: medium-dark skin tone + 🏄🏾‍♂ man surfing: medium-dark skin tone + 🏄🏿‍♂️ man surfing: dark skin tone + 🏄🏿‍♂ man surfing: dark skin tone + 🏄‍♀️ woman surfing + 🏄‍♀ woman surfing + 🏄🏻‍♀️ woman surfing: light skin tone + 🏄🏻‍♀ woman surfing: light skin tone + 🏄🏼‍♀️ woman surfing: medium-light skin tone + 🏄🏼‍♀ woman surfing: medium-light skin tone + 🏄🏽‍♀️ woman surfing: medium skin tone + 🏄🏽‍♀ woman surfing: medium skin tone + 🏄🏾‍♀️ woman surfing: medium-dark skin tone + 🏄🏾‍♀ woman surfing: medium-dark skin tone + 🏄🏿‍♀️ woman surfing: dark skin tone + 🏄🏿‍♀ woman surfing: dark skin tone + 🚣 person rowing boat + 🚣🏻 person rowing boat: light skin tone + 🚣🏼 person rowing boat: medium-light skin tone + 🚣🏽 person rowing boat: medium skin tone + 🚣🏾 person rowing boat: medium-dark skin tone + 🚣🏿 person rowing boat: dark skin tone + 🚣‍♂️ man rowing boat + 🚣‍♂ man rowing boat + 🚣🏻‍♂️ man rowing boat: light skin tone + 🚣🏻‍♂ man rowing boat: light skin tone + 🚣🏼‍♂️ man rowing boat: medium-light skin tone + 🚣🏼‍♂ man rowing boat: medium-light skin tone + 🚣🏽‍♂️ man rowing boat: medium skin tone + 🚣🏽‍♂ man rowing boat: medium skin tone + 🚣🏾‍♂️ man rowing boat: medium-dark skin tone + 🚣🏾‍♂ man rowing boat: medium-dark skin tone + 🚣🏿‍♂️ man rowing boat: dark skin tone + 🚣🏿‍♂ man rowing boat: dark skin tone + 🚣‍♀️ woman rowing boat + 🚣‍♀ woman rowing boat + 🚣🏻‍♀️ woman rowing boat: light skin tone + 🚣🏻‍♀ woman rowing boat: light skin tone + 🚣🏼‍♀️ woman rowing boat: medium-light skin tone + 🚣🏼‍♀ woman rowing boat: medium-light skin tone + 🚣🏽‍♀️ woman rowing boat: medium skin tone + 🚣🏽‍♀ woman rowing boat: medium skin tone + 🚣🏾‍♀️ woman rowing boat: medium-dark skin tone + 🚣🏾‍♀ woman rowing boat: medium-dark skin tone + 🚣🏿‍♀️ woman rowing boat: dark skin tone + 🚣🏿‍♀ woman rowing boat: dark skin tone + 🏊 person swimming + 🏊🏻 person swimming: light skin tone + 🏊🏼 person swimming: medium-light skin tone + 🏊🏽 person swimming: medium skin tone + 🏊🏾 person swimming: medium-dark skin tone + 🏊🏿 person swimming: dark skin tone + 🏊‍♂️ man swimming + 🏊‍♂ man swimming + 🏊🏻‍♂️ man swimming: light skin tone + 🏊🏻‍♂ man swimming: light skin tone + 🏊🏼‍♂️ man swimming: medium-light skin tone + 🏊🏼‍♂ man swimming: medium-light skin tone + 🏊🏽‍♂️ man swimming: medium skin tone + 🏊🏽‍♂ man swimming: medium skin tone + 🏊🏾‍♂️ man swimming: medium-dark skin tone + 🏊🏾‍♂ man swimming: medium-dark skin tone + 🏊🏿‍♂️ man swimming: dark skin tone + 🏊🏿‍♂ man swimming: dark skin tone + 🏊‍♀️ woman swimming + 🏊‍♀ woman swimming + 🏊🏻‍♀️ woman swimming: light skin tone + 🏊🏻‍♀ woman swimming: light skin tone + 🏊🏼‍♀️ woman swimming: medium-light skin tone + 🏊🏼‍♀ woman swimming: medium-light skin tone + 🏊🏽‍♀️ woman swimming: medium skin tone + 🏊🏽‍♀ woman swimming: medium skin tone + 🏊🏾‍♀️ woman swimming: medium-dark skin tone + 🏊🏾‍♀ woman swimming: medium-dark skin tone + 🏊🏿‍♀️ woman swimming: dark skin tone + 🏊🏿‍♀ woman swimming: dark skin tone + ⛹️ person bouncing ball + ⛹ person bouncing ball + ⛹🏻 person bouncing ball: light skin tone + ⛹🏼 person bouncing ball: medium-light skin tone + ⛹🏽 person bouncing ball: medium skin tone + ⛹🏾 person bouncing ball: medium-dark skin tone + ⛹🏿 person bouncing ball: dark skin tone + ⛹️‍♂️ man bouncing ball + ⛹‍♂️ man bouncing ball + ⛹️‍♂ man bouncing ball + ⛹‍♂ man bouncing ball + ⛹🏻‍♂️ man bouncing ball: light skin tone + ⛹🏻‍♂ man bouncing ball: light skin tone + ⛹🏼‍♂️ man bouncing ball: medium-light skin tone + ⛹🏼‍♂ man bouncing ball: medium-light skin tone + ⛹🏽‍♂️ man bouncing ball: medium skin tone + ⛹🏽‍♂ man bouncing ball: medium skin tone + ⛹🏾‍♂️ man bouncing ball: medium-dark skin tone + ⛹🏾‍♂ man bouncing ball: medium-dark skin tone + ⛹🏿‍♂️ man bouncing ball: dark skin tone + ⛹🏿‍♂ man bouncing ball: dark skin tone + ⛹️‍♀️ woman bouncing ball + ⛹‍♀️ woman bouncing ball + ⛹️‍♀ woman bouncing ball + ⛹‍♀ woman bouncing ball + ⛹🏻‍♀️ woman bouncing ball: light skin tone + ⛹🏻‍♀ woman bouncing ball: light skin tone + ⛹🏼‍♀️ woman bouncing ball: medium-light skin tone + ⛹🏼‍♀ woman bouncing ball: medium-light skin tone + ⛹🏽‍♀️ woman bouncing ball: medium skin tone + ⛹🏽‍♀ woman bouncing ball: medium skin tone + ⛹🏾‍♀️ woman bouncing ball: medium-dark skin tone + ⛹🏾‍♀ woman bouncing ball: medium-dark skin tone + ⛹🏿‍♀️ woman bouncing ball: dark skin tone + ⛹🏿‍♀ woman bouncing ball: dark skin tone + 🏋️ person lifting weights + 🏋 person lifting weights + 🏋🏻 person lifting weights: light skin tone + 🏋🏼 person lifting weights: medium-light skin tone + 🏋🏽 person lifting weights: medium skin tone + 🏋🏾 person lifting weights: medium-dark skin tone + 🏋🏿 person lifting weights: dark skin tone + 🏋️‍♂️ man lifting weights + 🏋‍♂️ man lifting weights + 🏋️‍♂ man lifting weights + 🏋‍♂ man lifting weights + 🏋🏻‍♂️ man lifting weights: light skin tone + 🏋🏻‍♂ man lifting weights: light skin tone + 🏋🏼‍♂️ man lifting weights: medium-light skin tone + 🏋🏼‍♂ man lifting weights: medium-light skin tone + 🏋🏽‍♂️ man lifting weights: medium skin tone + 🏋🏽‍♂ man lifting weights: medium skin tone + 🏋🏾‍♂️ man lifting weights: medium-dark skin tone + 🏋🏾‍♂ man lifting weights: medium-dark skin tone + 🏋🏿‍♂️ man lifting weights: dark skin tone + 🏋🏿‍♂ man lifting weights: dark skin tone + 🏋️‍♀️ woman lifting weights + 🏋‍♀️ woman lifting weights + 🏋️‍♀ woman lifting weights + 🏋‍♀ woman lifting weights + 🏋🏻‍♀️ woman lifting weights: light skin tone + 🏋🏻‍♀ woman lifting weights: light skin tone + 🏋🏼‍♀️ woman lifting weights: medium-light skin tone + 🏋🏼‍♀ woman lifting weights: medium-light skin tone + 🏋🏽‍♀️ woman lifting weights: medium skin tone + 🏋🏽‍♀ woman lifting weights: medium skin tone + 🏋🏾‍♀️ woman lifting weights: medium-dark skin tone + 🏋🏾‍♀ woman lifting weights: medium-dark skin tone + 🏋🏿‍♀️ woman lifting weights: dark skin tone + 🏋🏿‍♀ woman lifting weights: dark skin tone + 🚴 person biking + 🚴🏻 person biking: light skin tone + 🚴🏼 person biking: medium-light skin tone + 🚴🏽 person biking: medium skin tone + 🚴🏾 person biking: medium-dark skin tone + 🚴🏿 person biking: dark skin tone + 🚴‍♂️ man biking + 🚴‍♂ man biking + 🚴🏻‍♂️ man biking: light skin tone + 🚴🏻‍♂ man biking: light skin tone + 🚴🏼‍♂️ man biking: medium-light skin tone + 🚴🏼‍♂ man biking: medium-light skin tone + 🚴🏽‍♂️ man biking: medium skin tone + 🚴🏽‍♂ man biking: medium skin tone + 🚴🏾‍♂️ man biking: medium-dark skin tone + 🚴🏾‍♂ man biking: medium-dark skin tone + 🚴🏿‍♂️ man biking: dark skin tone + 🚴🏿‍♂ man biking: dark skin tone + 🚴‍♀️ woman biking + 🚴‍♀ woman biking + 🚴🏻‍♀️ woman biking: light skin tone + 🚴🏻‍♀ woman biking: light skin tone + 🚴🏼‍♀️ woman biking: medium-light skin tone + 🚴🏼‍♀ woman biking: medium-light skin tone + 🚴🏽‍♀️ woman biking: medium skin tone + 🚴🏽‍♀ woman biking: medium skin tone + 🚴🏾‍♀️ woman biking: medium-dark skin tone + 🚴🏾‍♀ woman biking: medium-dark skin tone + 🚴🏿‍♀️ woman biking: dark skin tone + 🚴🏿‍♀ woman biking: dark skin tone + 🚵 person mountain biking + 🚵🏻 person mountain biking: light skin tone + 🚵🏼 person mountain biking: medium-light skin tone + 🚵🏽 person mountain biking: medium skin tone + 🚵🏾 person mountain biking: medium-dark skin tone + 🚵🏿 person mountain biking: dark skin tone + 🚵‍♂️ man mountain biking + 🚵‍♂ man mountain biking + 🚵🏻‍♂️ man mountain biking: light skin tone + 🚵🏻‍♂ man mountain biking: light skin tone + 🚵🏼‍♂️ man mountain biking: medium-light skin tone + 🚵🏼‍♂ man mountain biking: medium-light skin tone + 🚵🏽‍♂️ man mountain biking: medium skin tone + 🚵🏽‍♂ man mountain biking: medium skin tone + 🚵🏾‍♂️ man mountain biking: medium-dark skin tone + 🚵🏾‍♂ man mountain biking: medium-dark skin tone + 🚵🏿‍♂️ man mountain biking: dark skin tone + 🚵🏿‍♂ man mountain biking: dark skin tone + 🚵‍♀️ woman mountain biking + 🚵‍♀ woman mountain biking + 🚵🏻‍♀️ woman mountain biking: light skin tone + 🚵🏻‍♀ woman mountain biking: light skin tone + 🚵🏼‍♀️ woman mountain biking: medium-light skin tone + 🚵🏼‍♀ woman mountain biking: medium-light skin tone + 🚵🏽‍♀️ woman mountain biking: medium skin tone + 🚵🏽‍♀ woman mountain biking: medium skin tone + 🚵🏾‍♀️ woman mountain biking: medium-dark skin tone + 🚵🏾‍♀ woman mountain biking: medium-dark skin tone + 🚵🏿‍♀️ woman mountain biking: dark skin tone + 🚵🏿‍♀ woman mountain biking: dark skin tone + 🤸 person cartwheeling + 🤸🏻 person cartwheeling: light skin tone + 🤸🏼 person cartwheeling: medium-light skin tone + 🤸🏽 person cartwheeling: medium skin tone + 🤸🏾 person cartwheeling: medium-dark skin tone + 🤸🏿 person cartwheeling: dark skin tone + 🤸‍♂️ man cartwheeling + 🤸‍♂ man cartwheeling + 🤸🏻‍♂️ man cartwheeling: light skin tone + 🤸🏻‍♂ man cartwheeling: light skin tone + 🤸🏼‍♂️ man cartwheeling: medium-light skin tone + 🤸🏼‍♂ man cartwheeling: medium-light skin tone + 🤸🏽‍♂️ man cartwheeling: medium skin tone + 🤸🏽‍♂ man cartwheeling: medium skin tone + 🤸🏾‍♂️ man cartwheeling: medium-dark skin tone + 🤸🏾‍♂ man cartwheeling: medium-dark skin tone + 🤸🏿‍♂️ man cartwheeling: dark skin tone + 🤸🏿‍♂ man cartwheeling: dark skin tone + 🤸‍♀️ woman cartwheeling + 🤸‍♀ woman cartwheeling + 🤸🏻‍♀️ woman cartwheeling: light skin tone + 🤸🏻‍♀ woman cartwheeling: light skin tone + 🤸🏼‍♀️ woman cartwheeling: medium-light skin tone + 🤸🏼‍♀ woman cartwheeling: medium-light skin tone + 🤸🏽‍♀️ woman cartwheeling: medium skin tone + 🤸🏽‍♀ woman cartwheeling: medium skin tone + 🤸🏾‍♀️ woman cartwheeling: medium-dark skin tone + 🤸🏾‍♀ woman cartwheeling: medium-dark skin tone + 🤸🏿‍♀️ woman cartwheeling: dark skin tone + 🤸🏿‍♀ woman cartwheeling: dark skin tone + 🤼 people wrestling + 🤼‍♂️ men wrestling + 🤼‍♂ men wrestling + 🤼‍♀️ women wrestling + 🤼‍♀ women wrestling + 🤽 person playing water polo + 🤽🏻 person playing water polo: light skin tone + 🤽🏼 person playing water polo: medium-light skin tone + 🤽🏽 person playing water polo: medium skin tone + 🤽🏾 person playing water polo: medium-dark skin tone + 🤽🏿 person playing water polo: dark skin tone + 🤽‍♂️ man playing water polo + 🤽‍♂ man playing water polo + 🤽🏻‍♂️ man playing water polo: light skin tone + 🤽🏻‍♂ man playing water polo: light skin tone + 🤽🏼‍♂️ man playing water polo: medium-light skin tone + 🤽🏼‍♂ man playing water polo: medium-light skin tone + 🤽🏽‍♂️ man playing water polo: medium skin tone + 🤽🏽‍♂ man playing water polo: medium skin tone + 🤽🏾‍♂️ man playing water polo: medium-dark skin tone + 🤽🏾‍♂ man playing water polo: medium-dark skin tone + 🤽🏿‍♂️ man playing water polo: dark skin tone + 🤽🏿‍♂ man playing water polo: dark skin tone + 🤽‍♀️ woman playing water polo + 🤽‍♀ woman playing water polo + 🤽🏻‍♀️ woman playing water polo: light skin tone + 🤽🏻‍♀ woman playing water polo: light skin tone + 🤽🏼‍♀️ woman playing water polo: medium-light skin tone + 🤽🏼‍♀ woman playing water polo: medium-light skin tone + 🤽🏽‍♀️ woman playing water polo: medium skin tone + 🤽🏽‍♀ woman playing water polo: medium skin tone + 🤽🏾‍♀️ woman playing water polo: medium-dark skin tone + 🤽🏾‍♀ woman playing water polo: medium-dark skin tone + 🤽🏿‍♀️ woman playing water polo: dark skin tone + 🤽🏿‍♀ woman playing water polo: dark skin tone + 🤾 person playing handball + 🤾🏻 person playing handball: light skin tone + 🤾🏼 person playing handball: medium-light skin tone + 🤾🏽 person playing handball: medium skin tone + 🤾🏾 person playing handball: medium-dark skin tone + 🤾🏿 person playing handball: dark skin tone + 🤾‍♂️ man playing handball + 🤾‍♂ man playing handball + 🤾🏻‍♂️ man playing handball: light skin tone + 🤾🏻‍♂ man playing handball: light skin tone + 🤾🏼‍♂️ man playing handball: medium-light skin tone + 🤾🏼‍♂ man playing handball: medium-light skin tone + 🤾🏽‍♂️ man playing handball: medium skin tone + 🤾🏽‍♂ man playing handball: medium skin tone + 🤾🏾‍♂️ man playing handball: medium-dark skin tone + 🤾🏾‍♂ man playing handball: medium-dark skin tone + 🤾🏿‍♂️ man playing handball: dark skin tone + 🤾🏿‍♂ man playing handball: dark skin tone + 🤾‍♀️ woman playing handball + 🤾‍♀ woman playing handball + 🤾🏻‍♀️ woman playing handball: light skin tone + 🤾🏻‍♀ woman playing handball: light skin tone + 🤾🏼‍♀️ woman playing handball: medium-light skin tone + 🤾🏼‍♀ woman playing handball: medium-light skin tone + 🤾🏽‍♀️ woman playing handball: medium skin tone + 🤾🏽‍♀ woman playing handball: medium skin tone + 🤾🏾‍♀️ woman playing handball: medium-dark skin tone + 🤾🏾‍♀ woman playing handball: medium-dark skin tone + 🤾🏿‍♀️ woman playing handball: dark skin tone + 🤾🏿‍♀ woman playing handball: dark skin tone + 🤹 person juggling + 🤹🏻 person juggling: light skin tone + 🤹🏼 person juggling: medium-light skin tone + 🤹🏽 person juggling: medium skin tone + 🤹🏾 person juggling: medium-dark skin tone + 🤹🏿 person juggling: dark skin tone + 🤹‍♂️ man juggling + 🤹‍♂ man juggling + 🤹🏻‍♂️ man juggling: light skin tone + 🤹🏻‍♂ man juggling: light skin tone + 🤹🏼‍♂️ man juggling: medium-light skin tone + 🤹🏼‍♂ man juggling: medium-light skin tone + 🤹🏽‍♂️ man juggling: medium skin tone + 🤹🏽‍♂ man juggling: medium skin tone + 🤹🏾‍♂️ man juggling: medium-dark skin tone + 🤹🏾‍♂ man juggling: medium-dark skin tone + 🤹🏿‍♂️ man juggling: dark skin tone + 🤹🏿‍♂ man juggling: dark skin tone + 🤹‍♀️ woman juggling + 🤹‍♀ woman juggling + 🤹🏻‍♀️ woman juggling: light skin tone + 🤹🏻‍♀ woman juggling: light skin tone + 🤹🏼‍♀️ woman juggling: medium-light skin tone + 🤹🏼‍♀ woman juggling: medium-light skin tone + 🤹🏽‍♀️ woman juggling: medium skin tone + 🤹🏽‍♀ woman juggling: medium skin tone + 🤹🏾‍♀️ woman juggling: medium-dark skin tone + 🤹🏾‍♀ woman juggling: medium-dark skin tone + 🤹🏿‍♀️ woman juggling: dark skin tone + 🤹🏿‍♀ woman juggling: dark skin tone + 🧘 person in lotus position + 🧘🏻 person in lotus position: light skin tone + 🧘🏼 person in lotus position: medium-light skin tone + 🧘🏽 person in lotus position: medium skin tone + 🧘🏾 person in lotus position: medium-dark skin tone + 🧘🏿 person in lotus position: dark skin tone + 🧘‍♂️ man in lotus position + 🧘‍♂ man in lotus position + 🧘🏻‍♂️ man in lotus position: light skin tone + 🧘🏻‍♂ man in lotus position: light skin tone + 🧘🏼‍♂️ man in lotus position: medium-light skin tone + 🧘🏼‍♂ man in lotus position: medium-light skin tone + 🧘🏽‍♂️ man in lotus position: medium skin tone + 🧘🏽‍♂ man in lotus position: medium skin tone + 🧘🏾‍♂️ man in lotus position: medium-dark skin tone + 🧘🏾‍♂ man in lotus position: medium-dark skin tone + 🧘🏿‍♂️ man in lotus position: dark skin tone + 🧘🏿‍♂ man in lotus position: dark skin tone + 🧘‍♀️ woman in lotus position + 🧘‍♀ woman in lotus position + 🧘🏻‍♀️ woman in lotus position: light skin tone + 🧘🏻‍♀ woman in lotus position: light skin tone + 🧘🏼‍♀️ woman in lotus position: medium-light skin tone + 🧘🏼‍♀ woman in lotus position: medium-light skin tone + 🧘🏽‍♀️ woman in lotus position: medium skin tone + 🧘🏽‍♀ woman in lotus position: medium skin tone + 🧘🏾‍♀️ woman in lotus position: medium-dark skin tone + 🧘🏾‍♀ woman in lotus position: medium-dark skin tone + 🧘🏿‍♀️ woman in lotus position: dark skin tone + 🧘🏿‍♀ woman in lotus position: dark skin tone + 🛀 person taking bath + 🛀🏻 person taking bath: light skin tone + 🛀🏼 person taking bath: medium-light skin tone + 🛀🏽 person taking bath: medium skin tone + 🛀🏾 person taking bath: medium-dark skin tone + 🛀🏿 person taking bath: dark skin tone + 🛌 person in bed + 🛌🏻 person in bed: light skin tone + 🛌🏼 person in bed: medium-light skin tone + 🛌🏽 person in bed: medium skin tone + 🛌🏾 person in bed: medium-dark skin tone + 🛌🏿 person in bed: dark skin tone + 🧑‍🤝‍🧑 people holding hands + 🧑🏻‍🤝‍🧑🏻 people holding hands: light skin tone + 🧑🏻‍🤝‍🧑🏼 people holding hands: light skin tone, medium-light skin tone + 🧑🏻‍🤝‍🧑🏽 people holding hands: light skin tone, medium skin tone + 🧑🏻‍🤝‍🧑🏾 people holding hands: light skin tone, medium-dark skin tone + 🧑🏻‍🤝‍🧑🏿 people holding hands: light skin tone, dark skin tone + 🧑🏼‍🤝‍🧑🏻 people holding hands: medium-light skin tone, light skin tone + 🧑🏼‍🤝‍🧑🏼 people holding hands: medium-light skin tone + 🧑🏼‍🤝‍🧑🏽 people holding hands: medium-light skin tone, medium skin tone + 🧑🏼‍🤝‍🧑🏾 people holding hands: medium-light skin tone, medium-dark skin tone + 🧑🏼‍🤝‍🧑🏿 people holding hands: medium-light skin tone, dark skin tone + 🧑🏽‍🤝‍🧑🏻 people holding hands: medium skin tone, light skin tone + 🧑🏽‍🤝‍🧑🏼 people holding hands: medium skin tone, medium-light skin tone + 🧑🏽‍🤝‍🧑🏽 people holding hands: medium skin tone + 🧑🏽‍🤝‍🧑🏾 people holding hands: medium skin tone, medium-dark skin tone + 🧑🏽‍🤝‍🧑🏿 people holding hands: medium skin tone, dark skin tone + 🧑🏾‍🤝‍🧑🏻 people holding hands: medium-dark skin tone, light skin tone + 🧑🏾‍🤝‍🧑🏼 people holding hands: medium-dark skin tone, medium-light skin tone + 🧑🏾‍🤝‍🧑🏽 people holding hands: medium-dark skin tone, medium skin tone + 🧑🏾‍🤝‍🧑🏾 people holding hands: medium-dark skin tone + 🧑🏾‍🤝‍🧑🏿 people holding hands: medium-dark skin tone, dark skin tone + 🧑🏿‍🤝‍🧑🏻 people holding hands: dark skin tone, light skin tone + 🧑🏿‍🤝‍🧑🏼 people holding hands: dark skin tone, medium-light skin tone + 🧑🏿‍🤝‍🧑🏽 people holding hands: dark skin tone, medium skin tone + 🧑🏿‍🤝‍🧑🏾 people holding hands: dark skin tone, medium-dark skin tone + 🧑🏿‍🤝‍🧑🏿 people holding hands: dark skin tone + 👭 women holding hands + 👭🏻 women holding hands: light skin tone + 👩🏻‍🤝‍👩🏼 women holding hands: light skin tone, medium-light skin tone + 👩🏻‍🤝‍👩🏽 women holding hands: light skin tone, medium skin tone + 👩🏻‍🤝‍👩🏾 women holding hands: light skin tone, medium-dark skin tone + 👩🏻‍🤝‍👩🏿 women holding hands: light skin tone, dark skin tone + 👩🏼‍🤝‍👩🏻 women holding hands: medium-light skin tone, light skin tone + 👭🏼 women holding hands: medium-light skin tone + 👩🏼‍🤝‍👩🏽 women holding hands: medium-light skin tone, medium skin tone + 👩🏼‍🤝‍👩🏾 women holding hands: medium-light skin tone, medium-dark skin tone + 👩🏼‍🤝‍👩🏿 women holding hands: medium-light skin tone, dark skin tone + 👩🏽‍🤝‍👩🏻 women holding hands: medium skin tone, light skin tone + 👩🏽‍🤝‍👩🏼 women holding hands: medium skin tone, medium-light skin tone + 👭🏽 women holding hands: medium skin tone + 👩🏽‍🤝‍👩🏾 women holding hands: medium skin tone, medium-dark skin tone + 👩🏽‍🤝‍👩🏿 women holding hands: medium skin tone, dark skin tone + 👩🏾‍🤝‍👩🏻 women holding hands: medium-dark skin tone, light skin tone + 👩🏾‍🤝‍👩🏼 women holding hands: medium-dark skin tone, medium-light skin tone + 👩🏾‍🤝‍👩🏽 women holding hands: medium-dark skin tone, medium skin tone + 👭🏾 women holding hands: medium-dark skin tone + 👩🏾‍🤝‍👩🏿 women holding hands: medium-dark skin tone, dark skin tone + 👩🏿‍🤝‍👩🏻 women holding hands: dark skin tone, light skin tone + 👩🏿‍🤝‍👩🏼 women holding hands: dark skin tone, medium-light skin tone + 👩🏿‍🤝‍👩🏽 women holding hands: dark skin tone, medium skin tone + 👩🏿‍🤝‍👩🏾 women holding hands: dark skin tone, medium-dark skin tone + 👭🏿 women holding hands: dark skin tone + 👫 woman and man holding hands + 👫🏻 woman and man holding hands: light skin tone + 👩🏻‍🤝‍👨🏼 woman and man holding hands: light skin tone, medium-light skin tone + 👩🏻‍🤝‍👨🏽 woman and man holding hands: light skin tone, medium skin tone + 👩🏻‍🤝‍👨🏾 woman and man holding hands: light skin tone, medium-dark skin tone + 👩🏻‍🤝‍👨🏿 woman and man holding hands: light skin tone, dark skin tone + 👩🏼‍🤝‍👨🏻 woman and man holding hands: medium-light skin tone, light skin tone + 👫🏼 woman and man holding hands: medium-light skin tone + 👩🏼‍🤝‍👨🏽 woman and man holding hands: medium-light skin tone, medium skin tone + 👩🏼‍🤝‍👨🏾 woman and man holding hands: medium-light skin tone, medium-dark skin tone + 👩🏼‍🤝‍👨🏿 woman and man holding hands: medium-light skin tone, dark skin tone + 👩🏽‍🤝‍👨🏻 woman and man holding hands: medium skin tone, light skin tone + 👩🏽‍🤝‍👨🏼 woman and man holding hands: medium skin tone, medium-light skin tone + 👫🏽 woman and man holding hands: medium skin tone + 👩🏽‍🤝‍👨🏾 woman and man holding hands: medium skin tone, medium-dark skin tone + 👩🏽‍🤝‍👨🏿 woman and man holding hands: medium skin tone, dark skin tone + 👩🏾‍🤝‍👨🏻 woman and man holding hands: medium-dark skin tone, light skin tone + 👩🏾‍🤝‍👨🏼 woman and man holding hands: medium-dark skin tone, medium-light skin tone + 👩🏾‍🤝‍👨🏽 woman and man holding hands: medium-dark skin tone, medium skin tone + 👫🏾 woman and man holding hands: medium-dark skin tone + 👩🏾‍🤝‍👨🏿 woman and man holding hands: medium-dark skin tone, dark skin tone + 👩🏿‍🤝‍👨🏻 woman and man holding hands: dark skin tone, light skin tone + 👩🏿‍🤝‍👨🏼 woman and man holding hands: dark skin tone, medium-light skin tone + 👩🏿‍🤝‍👨🏽 woman and man holding hands: dark skin tone, medium skin tone + 👩🏿‍🤝‍👨🏾 woman and man holding hands: dark skin tone, medium-dark skin tone + 👫🏿 woman and man holding hands: dark skin tone + 👬 men holding hands + 👬🏻 men holding hands: light skin tone + 👨🏻‍🤝‍👨🏼 men holding hands: light skin tone, medium-light skin tone + 👨🏻‍🤝‍👨🏽 men holding hands: light skin tone, medium skin tone + 👨🏻‍🤝‍👨🏾 men holding hands: light skin tone, medium-dark skin tone + 👨🏻‍🤝‍👨🏿 men holding hands: light skin tone, dark skin tone + 👨🏼‍🤝‍👨🏻 men holding hands: medium-light skin tone, light skin tone + 👬🏼 men holding hands: medium-light skin tone + 👨🏼‍🤝‍👨🏽 men holding hands: medium-light skin tone, medium skin tone + 👨🏼‍🤝‍👨🏾 men holding hands: medium-light skin tone, medium-dark skin tone + 👨🏼‍🤝‍👨🏿 men holding hands: medium-light skin tone, dark skin tone + 👨🏽‍🤝‍👨🏻 men holding hands: medium skin tone, light skin tone + 👨🏽‍🤝‍👨🏼 men holding hands: medium skin tone, medium-light skin tone + 👬🏽 men holding hands: medium skin tone + 👨🏽‍🤝‍👨🏾 men holding hands: medium skin tone, medium-dark skin tone + 👨🏽‍🤝‍👨🏿 men holding hands: medium skin tone, dark skin tone + 👨🏾‍🤝‍👨🏻 men holding hands: medium-dark skin tone, light skin tone + 👨🏾‍🤝‍👨🏼 men holding hands: medium-dark skin tone, medium-light skin tone + 👨🏾‍🤝‍👨🏽 men holding hands: medium-dark skin tone, medium skin tone + 👬🏾 men holding hands: medium-dark skin tone + 👨🏾‍🤝‍👨🏿 men holding hands: medium-dark skin tone, dark skin tone + 👨🏿‍🤝‍👨🏻 men holding hands: dark skin tone, light skin tone + 👨🏿‍🤝‍👨🏼 men holding hands: dark skin tone, medium-light skin tone + 👨🏿‍🤝‍👨🏽 men holding hands: dark skin tone, medium skin tone + 👨🏿‍🤝‍👨🏾 men holding hands: dark skin tone, medium-dark skin tone + 👬🏿 men holding hands: dark skin tone + 💏 kiss + 💏🏻 kiss: light skin tone + 💏🏼 kiss: medium-light skin tone + 💏🏽 kiss: medium skin tone + 💏🏾 kiss: medium-dark skin tone + 💏🏿 kiss: dark skin tone + 🧑🏻‍❤️‍💋‍🧑🏼 kiss: person, person, light skin tone, medium-light skin tone + 🧑🏻‍❤‍💋‍🧑🏼 kiss: person, person, light skin tone, medium-light skin tone + 🧑🏻‍❤️‍💋‍🧑🏽 kiss: person, person, light skin tone, medium skin tone + 🧑🏻‍❤‍💋‍🧑🏽 kiss: person, person, light skin tone, medium skin tone + 🧑🏻‍❤️‍💋‍🧑🏾 kiss: person, person, light skin tone, medium-dark skin tone + 🧑🏻‍❤‍💋‍🧑🏾 kiss: person, person, light skin tone, medium-dark skin tone + 🧑🏻‍❤️‍💋‍🧑🏿 kiss: person, person, light skin tone, dark skin tone + 🧑🏻‍❤‍💋‍🧑🏿 kiss: person, person, light skin tone, dark skin tone + 🧑🏼‍❤️‍💋‍🧑🏻 kiss: person, person, medium-light skin tone, light skin tone + 🧑🏼‍❤‍💋‍🧑🏻 kiss: person, person, medium-light skin tone, light skin tone + 🧑🏼‍❤️‍💋‍🧑🏽 kiss: person, person, medium-light skin tone, medium skin tone + 🧑🏼‍❤‍💋‍🧑🏽 kiss: person, person, medium-light skin tone, medium skin tone + 🧑🏼‍❤️‍💋‍🧑🏾 kiss: person, person, medium-light skin tone, medium-dark skin tone + 🧑🏼‍❤‍💋‍🧑🏾 kiss: person, person, medium-light skin tone, medium-dark skin tone + 🧑🏼‍❤️‍💋‍🧑🏿 kiss: person, person, medium-light skin tone, dark skin tone + 🧑🏼‍❤‍💋‍🧑🏿 kiss: person, person, medium-light skin tone, dark skin tone + 🧑🏽‍❤️‍💋‍🧑🏻 kiss: person, person, medium skin tone, light skin tone + 🧑🏽‍❤‍💋‍🧑🏻 kiss: person, person, medium skin tone, light skin tone + 🧑🏽‍❤️‍💋‍🧑🏼 kiss: person, person, medium skin tone, medium-light skin tone + 🧑🏽‍❤‍💋‍🧑🏼 kiss: person, person, medium skin tone, medium-light skin tone + 🧑🏽‍❤️‍💋‍🧑🏾 kiss: person, person, medium skin tone, medium-dark skin tone + 🧑🏽‍❤‍💋‍🧑🏾 kiss: person, person, medium skin tone, medium-dark skin tone + 🧑🏽‍❤️‍💋‍🧑🏿 kiss: person, person, medium skin tone, dark skin tone + 🧑🏽‍❤‍💋‍🧑🏿 kiss: person, person, medium skin tone, dark skin tone + 🧑🏾‍❤️‍💋‍🧑🏻 kiss: person, person, medium-dark skin tone, light skin tone + 🧑🏾‍❤‍💋‍🧑🏻 kiss: person, person, medium-dark skin tone, light skin tone + 🧑🏾‍❤️‍💋‍🧑🏼 kiss: person, person, medium-dark skin tone, medium-light skin tone + 🧑🏾‍❤‍💋‍🧑🏼 kiss: person, person, medium-dark skin tone, medium-light skin tone + 🧑🏾‍❤️‍💋‍🧑🏽 kiss: person, person, medium-dark skin tone, medium skin tone + 🧑🏾‍❤‍💋‍🧑🏽 kiss: person, person, medium-dark skin tone, medium skin tone + 🧑🏾‍❤️‍💋‍🧑🏿 kiss: person, person, medium-dark skin tone, dark skin tone + 🧑🏾‍❤‍💋‍🧑🏿 kiss: person, person, medium-dark skin tone, dark skin tone + 🧑🏿‍❤️‍💋‍🧑🏻 kiss: person, person, dark skin tone, light skin tone + 🧑🏿‍❤‍💋‍🧑🏻 kiss: person, person, dark skin tone, light skin tone + 🧑🏿‍❤️‍💋‍🧑🏼 kiss: person, person, dark skin tone, medium-light skin tone + 🧑🏿‍❤‍💋‍🧑🏼 kiss: person, person, dark skin tone, medium-light skin tone + 🧑🏿‍❤️‍💋‍🧑🏽 kiss: person, person, dark skin tone, medium skin tone + 🧑🏿‍❤‍💋‍🧑🏽 kiss: person, person, dark skin tone, medium skin tone + 🧑🏿‍❤️‍💋‍🧑🏾 kiss: person, person, dark skin tone, medium-dark skin tone + 🧑🏿‍❤‍💋‍🧑🏾 kiss: person, person, dark skin tone, medium-dark skin tone + 👩‍❤️‍💋‍👨 kiss: woman, man + 👩‍❤‍💋‍👨 kiss: woman, man + 👩🏻‍❤️‍💋‍👨🏻 kiss: woman, man, light skin tone + 👩🏻‍❤‍💋‍👨🏻 kiss: woman, man, light skin tone + 👩🏻‍❤️‍💋‍👨🏼 kiss: woman, man, light skin tone, medium-light skin tone + 👩🏻‍❤‍💋‍👨🏼 kiss: woman, man, light skin tone, medium-light skin tone + 👩🏻‍❤️‍💋‍👨🏽 kiss: woman, man, light skin tone, medium skin tone + 👩🏻‍❤‍💋‍👨🏽 kiss: woman, man, light skin tone, medium skin tone + 👩🏻‍❤️‍💋‍👨🏾 kiss: woman, man, light skin tone, medium-dark skin tone + 👩🏻‍❤‍💋‍👨🏾 kiss: woman, man, light skin tone, medium-dark skin tone + 👩🏻‍❤️‍💋‍👨🏿 kiss: woman, man, light skin tone, dark skin tone + 👩🏻‍❤‍💋‍👨🏿 kiss: woman, man, light skin tone, dark skin tone + 👩🏼‍❤️‍💋‍👨🏻 kiss: woman, man, medium-light skin tone, light skin tone + 👩🏼‍❤‍💋‍👨🏻 kiss: woman, man, medium-light skin tone, light skin tone + 👩🏼‍❤️‍💋‍👨🏼 kiss: woman, man, medium-light skin tone + 👩🏼‍❤‍💋‍👨🏼 kiss: woman, man, medium-light skin tone + 👩🏼‍❤️‍💋‍👨🏽 kiss: woman, man, medium-light skin tone, medium skin tone + 👩🏼‍❤‍💋‍👨🏽 kiss: woman, man, medium-light skin tone, medium skin tone + 👩🏼‍❤️‍💋‍👨🏾 kiss: woman, man, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤‍💋‍👨🏾 kiss: woman, man, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤️‍💋‍👨🏿 kiss: woman, man, medium-light skin tone, dark skin tone + 👩🏼‍❤‍💋‍👨🏿 kiss: woman, man, medium-light skin tone, dark skin tone + 👩🏽‍❤️‍💋‍👨🏻 kiss: woman, man, medium skin tone, light skin tone + 👩🏽‍❤‍💋‍👨🏻 kiss: woman, man, medium skin tone, light skin tone + 👩🏽‍❤️‍💋‍👨🏼 kiss: woman, man, medium skin tone, medium-light skin tone + 👩🏽‍❤‍💋‍👨🏼 kiss: woman, man, medium skin tone, medium-light skin tone + 👩🏽‍❤️‍💋‍👨🏽 kiss: woman, man, medium skin tone + 👩🏽‍❤‍💋‍👨🏽 kiss: woman, man, medium skin tone + 👩🏽‍❤️‍💋‍👨🏾 kiss: woman, man, medium skin tone, medium-dark skin tone + 👩🏽‍❤‍💋‍👨🏾 kiss: woman, man, medium skin tone, medium-dark skin tone + 👩🏽‍❤️‍💋‍👨🏿 kiss: woman, man, medium skin tone, dark skin tone + 👩🏽‍❤‍💋‍👨🏿 kiss: woman, man, medium skin tone, dark skin tone + 👩🏾‍❤️‍💋‍👨🏻 kiss: woman, man, medium-dark skin tone, light skin tone + 👩🏾‍❤‍💋‍👨🏻 kiss: woman, man, medium-dark skin tone, light skin tone + 👩🏾‍❤️‍💋‍👨🏼 kiss: woman, man, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤‍💋‍👨🏼 kiss: woman, man, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤️‍💋‍👨🏽 kiss: woman, man, medium-dark skin tone, medium skin tone + 👩🏾‍❤‍💋‍👨🏽 kiss: woman, man, medium-dark skin tone, medium skin tone + 👩🏾‍❤️‍💋‍👨🏾 kiss: woman, man, medium-dark skin tone + 👩🏾‍❤‍💋‍👨🏾 kiss: woman, man, medium-dark skin tone + 👩🏾‍❤️‍💋‍👨🏿 kiss: woman, man, medium-dark skin tone, dark skin tone + 👩🏾‍❤‍💋‍👨🏿 kiss: woman, man, medium-dark skin tone, dark skin tone + 👩🏿‍❤️‍💋‍👨🏻 kiss: woman, man, dark skin tone, light skin tone + 👩🏿‍❤‍💋‍👨🏻 kiss: woman, man, dark skin tone, light skin tone + 👩🏿‍❤️‍💋‍👨🏼 kiss: woman, man, dark skin tone, medium-light skin tone + 👩🏿‍❤‍💋‍👨🏼 kiss: woman, man, dark skin tone, medium-light skin tone + 👩🏿‍❤️‍💋‍👨🏽 kiss: woman, man, dark skin tone, medium skin tone + 👩🏿‍❤‍💋‍👨🏽 kiss: woman, man, dark skin tone, medium skin tone + 👩🏿‍❤️‍💋‍👨🏾 kiss: woman, man, dark skin tone, medium-dark skin tone + 👩🏿‍❤‍💋‍👨🏾 kiss: woman, man, dark skin tone, medium-dark skin tone + 👩🏿‍❤️‍💋‍👨🏿 kiss: woman, man, dark skin tone + 👩🏿‍❤‍💋‍👨🏿 kiss: woman, man, dark skin tone + 👨‍❤️‍💋‍👨 kiss: man, man + 👨‍❤‍💋‍👨 kiss: man, man + 👨🏻‍❤️‍💋‍👨🏻 kiss: man, man, light skin tone + 👨🏻‍❤‍💋‍👨🏻 kiss: man, man, light skin tone + 👨🏻‍❤️‍💋‍👨🏼 kiss: man, man, light skin tone, medium-light skin tone + 👨🏻‍❤‍💋‍👨🏼 kiss: man, man, light skin tone, medium-light skin tone + 👨🏻‍❤️‍💋‍👨🏽 kiss: man, man, light skin tone, medium skin tone + 👨🏻‍❤‍💋‍👨🏽 kiss: man, man, light skin tone, medium skin tone + 👨🏻‍❤️‍💋‍👨🏾 kiss: man, man, light skin tone, medium-dark skin tone + 👨🏻‍❤‍💋‍👨🏾 kiss: man, man, light skin tone, medium-dark skin tone + 👨🏻‍❤️‍💋‍👨🏿 kiss: man, man, light skin tone, dark skin tone + 👨🏻‍❤‍💋‍👨🏿 kiss: man, man, light skin tone, dark skin tone + 👨🏼‍❤️‍💋‍👨🏻 kiss: man, man, medium-light skin tone, light skin tone + 👨🏼‍❤‍💋‍👨🏻 kiss: man, man, medium-light skin tone, light skin tone + 👨🏼‍❤️‍💋‍👨🏼 kiss: man, man, medium-light skin tone + 👨🏼‍❤‍💋‍👨🏼 kiss: man, man, medium-light skin tone + 👨🏼‍❤️‍💋‍👨🏽 kiss: man, man, medium-light skin tone, medium skin tone + 👨🏼‍❤‍💋‍👨🏽 kiss: man, man, medium-light skin tone, medium skin tone + 👨🏼‍❤️‍💋‍👨🏾 kiss: man, man, medium-light skin tone, medium-dark skin tone + 👨🏼‍❤‍💋‍👨🏾 kiss: man, man, medium-light skin tone, medium-dark skin tone + 👨🏼‍❤️‍💋‍👨🏿 kiss: man, man, medium-light skin tone, dark skin tone + 👨🏼‍❤‍💋‍👨🏿 kiss: man, man, medium-light skin tone, dark skin tone + 👨🏽‍❤️‍💋‍👨🏻 kiss: man, man, medium skin tone, light skin tone + 👨🏽‍❤‍💋‍👨🏻 kiss: man, man, medium skin tone, light skin tone + 👨🏽‍❤️‍💋‍👨🏼 kiss: man, man, medium skin tone, medium-light skin tone + 👨🏽‍❤‍💋‍👨🏼 kiss: man, man, medium skin tone, medium-light skin tone + 👨🏽‍❤️‍💋‍👨🏽 kiss: man, man, medium skin tone + 👨🏽‍❤‍💋‍👨🏽 kiss: man, man, medium skin tone + 👨🏽‍❤️‍💋‍👨🏾 kiss: man, man, medium skin tone, medium-dark skin tone + 👨🏽‍❤‍💋‍👨🏾 kiss: man, man, medium skin tone, medium-dark skin tone + 👨🏽‍❤️‍💋‍👨🏿 kiss: man, man, medium skin tone, dark skin tone + 👨🏽‍❤‍💋‍👨🏿 kiss: man, man, medium skin tone, dark skin tone + 👨🏾‍❤️‍💋‍👨🏻 kiss: man, man, medium-dark skin tone, light skin tone + 👨🏾‍❤‍💋‍👨🏻 kiss: man, man, medium-dark skin tone, light skin tone + 👨🏾‍❤️‍💋‍👨🏼 kiss: man, man, medium-dark skin tone, medium-light skin tone + 👨🏾‍❤‍💋‍👨🏼 kiss: man, man, medium-dark skin tone, medium-light skin tone + 👨🏾‍❤️‍💋‍👨🏽 kiss: man, man, medium-dark skin tone, medium skin tone + 👨🏾‍❤‍💋‍👨🏽 kiss: man, man, medium-dark skin tone, medium skin tone + 👨🏾‍❤️‍💋‍👨🏾 kiss: man, man, medium-dark skin tone + 👨🏾‍❤‍💋‍👨🏾 kiss: man, man, medium-dark skin tone + 👨🏾‍❤️‍💋‍👨🏿 kiss: man, man, medium-dark skin tone, dark skin tone + 👨🏾‍❤‍💋‍👨🏿 kiss: man, man, medium-dark skin tone, dark skin tone + 👨🏿‍❤️‍💋‍👨🏻 kiss: man, man, dark skin tone, light skin tone + 👨🏿‍❤‍💋‍👨🏻 kiss: man, man, dark skin tone, light skin tone + 👨🏿‍❤️‍💋‍👨🏼 kiss: man, man, dark skin tone, medium-light skin tone + 👨🏿‍❤‍💋‍👨🏼 kiss: man, man, dark skin tone, medium-light skin tone + 👨🏿‍❤️‍💋‍👨🏽 kiss: man, man, dark skin tone, medium skin tone + 👨🏿‍❤‍💋‍👨🏽 kiss: man, man, dark skin tone, medium skin tone + 👨🏿‍❤️‍💋‍👨🏾 kiss: man, man, dark skin tone, medium-dark skin tone + 👨🏿‍❤‍💋‍👨🏾 kiss: man, man, dark skin tone, medium-dark skin tone + 👨🏿‍❤️‍💋‍👨🏿 kiss: man, man, dark skin tone + 👨🏿‍❤‍💋‍👨🏿 kiss: man, man, dark skin tone + 👩‍❤️‍💋‍👩 kiss: woman, woman + 👩‍❤‍💋‍👩 kiss: woman, woman + 👩🏻‍❤️‍💋‍👩🏻 kiss: woman, woman, light skin tone + 👩🏻‍❤‍💋‍👩🏻 kiss: woman, woman, light skin tone + 👩🏻‍❤️‍💋‍👩🏼 kiss: woman, woman, light skin tone, medium-light skin tone + 👩🏻‍❤‍💋‍👩🏼 kiss: woman, woman, light skin tone, medium-light skin tone + 👩🏻‍❤️‍💋‍👩🏽 kiss: woman, woman, light skin tone, medium skin tone + 👩🏻‍❤‍💋‍👩🏽 kiss: woman, woman, light skin tone, medium skin tone + 👩🏻‍❤️‍💋‍👩🏾 kiss: woman, woman, light skin tone, medium-dark skin tone + 👩🏻‍❤‍💋‍👩🏾 kiss: woman, woman, light skin tone, medium-dark skin tone + 👩🏻‍❤️‍💋‍👩🏿 kiss: woman, woman, light skin tone, dark skin tone + 👩🏻‍❤‍💋‍👩🏿 kiss: woman, woman, light skin tone, dark skin tone + 👩🏼‍❤️‍💋‍👩🏻 kiss: woman, woman, medium-light skin tone, light skin tone + 👩🏼‍❤‍💋‍👩🏻 kiss: woman, woman, medium-light skin tone, light skin tone + 👩🏼‍❤️‍💋‍👩🏼 kiss: woman, woman, medium-light skin tone + 👩🏼‍❤‍💋‍👩🏼 kiss: woman, woman, medium-light skin tone + 👩🏼‍❤️‍💋‍👩🏽 kiss: woman, woman, medium-light skin tone, medium skin tone + 👩🏼‍❤‍💋‍👩🏽 kiss: woman, woman, medium-light skin tone, medium skin tone + 👩🏼‍❤️‍💋‍👩🏾 kiss: woman, woman, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤‍💋‍👩🏾 kiss: woman, woman, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤️‍💋‍👩🏿 kiss: woman, woman, medium-light skin tone, dark skin tone + 👩🏼‍❤‍💋‍👩🏿 kiss: woman, woman, medium-light skin tone, dark skin tone + 👩🏽‍❤️‍💋‍👩🏻 kiss: woman, woman, medium skin tone, light skin tone + 👩🏽‍❤‍💋‍👩🏻 kiss: woman, woman, medium skin tone, light skin tone + 👩🏽‍❤️‍💋‍👩🏼 kiss: woman, woman, medium skin tone, medium-light skin tone + 👩🏽‍❤‍💋‍👩🏼 kiss: woman, woman, medium skin tone, medium-light skin tone + 👩🏽‍❤️‍💋‍👩🏽 kiss: woman, woman, medium skin tone + 👩🏽‍❤‍💋‍👩🏽 kiss: woman, woman, medium skin tone + 👩🏽‍❤️‍💋‍👩🏾 kiss: woman, woman, medium skin tone, medium-dark skin tone + 👩🏽‍❤‍💋‍👩🏾 kiss: woman, woman, medium skin tone, medium-dark skin tone + 👩🏽‍❤️‍💋‍👩🏿 kiss: woman, woman, medium skin tone, dark skin tone + 👩🏽‍❤‍💋‍👩🏿 kiss: woman, woman, medium skin tone, dark skin tone + 👩🏾‍❤️‍💋‍👩🏻 kiss: woman, woman, medium-dark skin tone, light skin tone + 👩🏾‍❤‍💋‍👩🏻 kiss: woman, woman, medium-dark skin tone, light skin tone + 👩🏾‍❤️‍💋‍👩🏼 kiss: woman, woman, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤‍💋‍👩🏼 kiss: woman, woman, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤️‍💋‍👩🏽 kiss: woman, woman, medium-dark skin tone, medium skin tone + 👩🏾‍❤‍💋‍👩🏽 kiss: woman, woman, medium-dark skin tone, medium skin tone + 👩🏾‍❤️‍💋‍👩🏾 kiss: woman, woman, medium-dark skin tone + 👩🏾‍❤‍💋‍👩🏾 kiss: woman, woman, medium-dark skin tone + 👩🏾‍❤️‍💋‍👩🏿 kiss: woman, woman, medium-dark skin tone, dark skin tone + 👩🏾‍❤‍💋‍👩🏿 kiss: woman, woman, medium-dark skin tone, dark skin tone + 👩🏿‍❤️‍💋‍👩🏻 kiss: woman, woman, dark skin tone, light skin tone + 👩🏿‍❤‍💋‍👩🏻 kiss: woman, woman, dark skin tone, light skin tone + 👩🏿‍❤️‍💋‍👩🏼 kiss: woman, woman, dark skin tone, medium-light skin tone + 👩🏿‍❤‍💋‍👩🏼 kiss: woman, woman, dark skin tone, medium-light skin tone + 👩🏿‍❤️‍💋‍👩🏽 kiss: woman, woman, dark skin tone, medium skin tone + 👩🏿‍❤‍💋‍👩🏽 kiss: woman, woman, dark skin tone, medium skin tone + 👩🏿‍❤️‍💋‍👩🏾 kiss: woman, woman, dark skin tone, medium-dark skin tone + 👩🏿‍❤‍💋‍👩🏾 kiss: woman, woman, dark skin tone, medium-dark skin tone + 👩🏿‍❤️‍💋‍👩🏿 kiss: woman, woman, dark skin tone + 👩🏿‍❤‍💋‍👩🏿 kiss: woman, woman, dark skin tone + 💑 couple with heart + 💑🏻 couple with heart: light skin tone + 💑🏼 couple with heart: medium-light skin tone + 💑🏽 couple with heart: medium skin tone + 💑🏾 couple with heart: medium-dark skin tone + 💑🏿 couple with heart: dark skin tone + 🧑🏻‍❤️‍🧑🏼 couple with heart: person, person, light skin tone, medium-light skin tone + 🧑🏻‍❤‍🧑🏼 couple with heart: person, person, light skin tone, medium-light skin tone + 🧑🏻‍❤️‍🧑🏽 couple with heart: person, person, light skin tone, medium skin tone + 🧑🏻‍❤‍🧑🏽 couple with heart: person, person, light skin tone, medium skin tone + 🧑🏻‍❤️‍🧑🏾 couple with heart: person, person, light skin tone, medium-dark skin tone + 🧑🏻‍❤‍🧑🏾 couple with heart: person, person, light skin tone, medium-dark skin tone + 🧑🏻‍❤️‍🧑🏿 couple with heart: person, person, light skin tone, dark skin tone + 🧑🏻‍❤‍🧑🏿 couple with heart: person, person, light skin tone, dark skin tone + 🧑🏼‍❤️‍🧑🏻 couple with heart: person, person, medium-light skin tone, light skin tone + 🧑🏼‍❤‍🧑🏻 couple with heart: person, person, medium-light skin tone, light skin tone + 🧑🏼‍❤️‍🧑🏽 couple with heart: person, person, medium-light skin tone, medium skin tone + 🧑🏼‍❤‍🧑🏽 couple with heart: person, person, medium-light skin tone, medium skin tone + 🧑🏼‍❤️‍🧑🏾 couple with heart: person, person, medium-light skin tone, medium-dark skin tone + 🧑🏼‍❤‍🧑🏾 couple with heart: person, person, medium-light skin tone, medium-dark skin tone + 🧑🏼‍❤️‍🧑🏿 couple with heart: person, person, medium-light skin tone, dark skin tone + 🧑🏼‍❤‍🧑🏿 couple with heart: person, person, medium-light skin tone, dark skin tone + 🧑🏽‍❤️‍🧑🏻 couple with heart: person, person, medium skin tone, light skin tone + 🧑🏽‍❤‍🧑🏻 couple with heart: person, person, medium skin tone, light skin tone + 🧑🏽‍❤️‍🧑🏼 couple with heart: person, person, medium skin tone, medium-light skin tone + 🧑🏽‍❤‍🧑🏼 couple with heart: person, person, medium skin tone, medium-light skin tone + 🧑🏽‍❤️‍🧑🏾 couple with heart: person, person, medium skin tone, medium-dark skin tone + 🧑🏽‍❤‍🧑🏾 couple with heart: person, person, medium skin tone, medium-dark skin tone + 🧑🏽‍❤️‍🧑🏿 couple with heart: person, person, medium skin tone, dark skin tone + 🧑🏽‍❤‍🧑🏿 couple with heart: person, person, medium skin tone, dark skin tone + 🧑🏾‍❤️‍🧑🏻 couple with heart: person, person, medium-dark skin tone, light skin tone + 🧑🏾‍❤‍🧑🏻 couple with heart: person, person, medium-dark skin tone, light skin tone + 🧑🏾‍❤️‍🧑🏼 couple with heart: person, person, medium-dark skin tone, medium-light skin tone + 🧑🏾‍❤‍🧑🏼 couple with heart: person, person, medium-dark skin tone, medium-light skin tone + 🧑🏾‍❤️‍🧑🏽 couple with heart: person, person, medium-dark skin tone, medium skin tone + 🧑🏾‍❤‍🧑🏽 couple with heart: person, person, medium-dark skin tone, medium skin tone + 🧑🏾‍❤️‍🧑🏿 couple with heart: person, person, medium-dark skin tone, dark skin tone + 🧑🏾‍❤‍🧑🏿 couple with heart: person, person, medium-dark skin tone, dark skin tone + 🧑🏿‍❤️‍🧑🏻 couple with heart: person, person, dark skin tone, light skin tone + 🧑🏿‍❤‍🧑🏻 couple with heart: person, person, dark skin tone, light skin tone + 🧑🏿‍❤️‍🧑🏼 couple with heart: person, person, dark skin tone, medium-light skin tone + 🧑🏿‍❤‍🧑🏼 couple with heart: person, person, dark skin tone, medium-light skin tone + 🧑🏿‍❤️‍🧑🏽 couple with heart: person, person, dark skin tone, medium skin tone + 🧑🏿‍❤‍🧑🏽 couple with heart: person, person, dark skin tone, medium skin tone + 🧑🏿‍❤️‍🧑🏾 couple with heart: person, person, dark skin tone, medium-dark skin tone + 🧑🏿‍❤‍🧑🏾 couple with heart: person, person, dark skin tone, medium-dark skin tone + 👩‍❤️‍👨 couple with heart: woman, man + 👩‍❤‍👨 couple with heart: woman, man + 👩🏻‍❤️‍👨🏻 couple with heart: woman, man, light skin tone + 👩🏻‍❤‍👨🏻 couple with heart: woman, man, light skin tone + 👩🏻‍❤️‍👨🏼 couple with heart: woman, man, light skin tone, medium-light skin tone + 👩🏻‍❤‍👨🏼 couple with heart: woman, man, light skin tone, medium-light skin tone + 👩🏻‍❤️‍👨🏽 couple with heart: woman, man, light skin tone, medium skin tone + 👩🏻‍❤‍👨🏽 couple with heart: woman, man, light skin tone, medium skin tone + 👩🏻‍❤️‍👨🏾 couple with heart: woman, man, light skin tone, medium-dark skin tone + 👩🏻‍❤‍👨🏾 couple with heart: woman, man, light skin tone, medium-dark skin tone + 👩🏻‍❤️‍👨🏿 couple with heart: woman, man, light skin tone, dark skin tone + 👩🏻‍❤‍👨🏿 couple with heart: woman, man, light skin tone, dark skin tone + 👩🏼‍❤️‍👨🏻 couple with heart: woman, man, medium-light skin tone, light skin tone + 👩🏼‍❤‍👨🏻 couple with heart: woman, man, medium-light skin tone, light skin tone + 👩🏼‍❤️‍👨🏼 couple with heart: woman, man, medium-light skin tone + 👩🏼‍❤‍👨🏼 couple with heart: woman, man, medium-light skin tone + 👩🏼‍❤️‍👨🏽 couple with heart: woman, man, medium-light skin tone, medium skin tone + 👩🏼‍❤‍👨🏽 couple with heart: woman, man, medium-light skin tone, medium skin tone + 👩🏼‍❤️‍👨🏾 couple with heart: woman, man, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤‍👨🏾 couple with heart: woman, man, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤️‍👨🏿 couple with heart: woman, man, medium-light skin tone, dark skin tone + 👩🏼‍❤‍👨🏿 couple with heart: woman, man, medium-light skin tone, dark skin tone + 👩🏽‍❤️‍👨🏻 couple with heart: woman, man, medium skin tone, light skin tone + 👩🏽‍❤‍👨🏻 couple with heart: woman, man, medium skin tone, light skin tone + 👩🏽‍❤️‍👨🏼 couple with heart: woman, man, medium skin tone, medium-light skin tone + 👩🏽‍❤‍👨🏼 couple with heart: woman, man, medium skin tone, medium-light skin tone + 👩🏽‍❤️‍👨🏽 couple with heart: woman, man, medium skin tone + 👩🏽‍❤‍👨🏽 couple with heart: woman, man, medium skin tone + 👩🏽‍❤️‍👨🏾 couple with heart: woman, man, medium skin tone, medium-dark skin tone + 👩🏽‍❤‍👨🏾 couple with heart: woman, man, medium skin tone, medium-dark skin tone + 👩🏽‍❤️‍👨🏿 couple with heart: woman, man, medium skin tone, dark skin tone + 👩🏽‍❤‍👨🏿 couple with heart: woman, man, medium skin tone, dark skin tone + 👩🏾‍❤️‍👨🏻 couple with heart: woman, man, medium-dark skin tone, light skin tone + 👩🏾‍❤‍👨🏻 couple with heart: woman, man, medium-dark skin tone, light skin tone + 👩🏾‍❤️‍👨🏼 couple with heart: woman, man, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤‍👨🏼 couple with heart: woman, man, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤️‍👨🏽 couple with heart: woman, man, medium-dark skin tone, medium skin tone + 👩🏾‍❤‍👨🏽 couple with heart: woman, man, medium-dark skin tone, medium skin tone + 👩🏾‍❤️‍👨🏾 couple with heart: woman, man, medium-dark skin tone + 👩🏾‍❤‍👨🏾 couple with heart: woman, man, medium-dark skin tone + 👩🏾‍❤️‍👨🏿 couple with heart: woman, man, medium-dark skin tone, dark skin tone + 👩🏾‍❤‍👨🏿 couple with heart: woman, man, medium-dark skin tone, dark skin tone + 👩🏿‍❤️‍👨🏻 couple with heart: woman, man, dark skin tone, light skin tone + 👩🏿‍❤‍👨🏻 couple with heart: woman, man, dark skin tone, light skin tone + 👩🏿‍❤️‍👨🏼 couple with heart: woman, man, dark skin tone, medium-light skin tone + 👩🏿‍❤‍👨🏼 couple with heart: woman, man, dark skin tone, medium-light skin tone + 👩🏿‍❤️‍👨🏽 couple with heart: woman, man, dark skin tone, medium skin tone + 👩🏿‍❤‍👨🏽 couple with heart: woman, man, dark skin tone, medium skin tone + 👩🏿‍❤️‍👨🏾 couple with heart: woman, man, dark skin tone, medium-dark skin tone + 👩🏿‍❤‍👨🏾 couple with heart: woman, man, dark skin tone, medium-dark skin tone + 👩🏿‍❤️‍👨🏿 couple with heart: woman, man, dark skin tone + 👩🏿‍❤‍👨🏿 couple with heart: woman, man, dark skin tone + 👨‍❤️‍👨 couple with heart: man, man + 👨‍❤‍👨 couple with heart: man, man + 👨🏻‍❤️‍👨🏻 couple with heart: man, man, light skin tone + 👨🏻‍❤‍👨🏻 couple with heart: man, man, light skin tone + 👨🏻‍❤️‍👨🏼 couple with heart: man, man, light skin tone, medium-light skin tone + 👨🏻‍❤‍👨🏼 couple with heart: man, man, light skin tone, medium-light skin tone + 👨🏻‍❤️‍👨🏽 couple with heart: man, man, light skin tone, medium skin tone + 👨🏻‍❤‍👨🏽 couple with heart: man, man, light skin tone, medium skin tone + 👨🏻‍❤️‍👨🏾 couple with heart: man, man, light skin tone, medium-dark skin tone + 👨🏻‍❤‍👨🏾 couple with heart: man, man, light skin tone, medium-dark skin tone + 👨🏻‍❤️‍👨🏿 couple with heart: man, man, light skin tone, dark skin tone + 👨🏻‍❤‍👨🏿 couple with heart: man, man, light skin tone, dark skin tone + 👨🏼‍❤️‍👨🏻 couple with heart: man, man, medium-light skin tone, light skin tone + 👨🏼‍❤‍👨🏻 couple with heart: man, man, medium-light skin tone, light skin tone + 👨🏼‍❤️‍👨🏼 couple with heart: man, man, medium-light skin tone + 👨🏼‍❤‍👨🏼 couple with heart: man, man, medium-light skin tone + 👨🏼‍❤️‍👨🏽 couple with heart: man, man, medium-light skin tone, medium skin tone + 👨🏼‍❤‍👨🏽 couple with heart: man, man, medium-light skin tone, medium skin tone + 👨🏼‍❤️‍👨🏾 couple with heart: man, man, medium-light skin tone, medium-dark skin tone + 👨🏼‍❤‍👨🏾 couple with heart: man, man, medium-light skin tone, medium-dark skin tone + 👨🏼‍❤️‍👨🏿 couple with heart: man, man, medium-light skin tone, dark skin tone + 👨🏼‍❤‍👨🏿 couple with heart: man, man, medium-light skin tone, dark skin tone + 👨🏽‍❤️‍👨🏻 couple with heart: man, man, medium skin tone, light skin tone + 👨🏽‍❤‍👨🏻 couple with heart: man, man, medium skin tone, light skin tone + 👨🏽‍❤️‍👨🏼 couple with heart: man, man, medium skin tone, medium-light skin tone + 👨🏽‍❤‍👨🏼 couple with heart: man, man, medium skin tone, medium-light skin tone + 👨🏽‍❤️‍👨🏽 couple with heart: man, man, medium skin tone + 👨🏽‍❤‍👨🏽 couple with heart: man, man, medium skin tone + 👨🏽‍❤️‍👨🏾 couple with heart: man, man, medium skin tone, medium-dark skin tone + 👨🏽‍❤‍👨🏾 couple with heart: man, man, medium skin tone, medium-dark skin tone + 👨🏽‍❤️‍👨🏿 couple with heart: man, man, medium skin tone, dark skin tone + 👨🏽‍❤‍👨🏿 couple with heart: man, man, medium skin tone, dark skin tone + 👨🏾‍❤️‍👨🏻 couple with heart: man, man, medium-dark skin tone, light skin tone + 👨🏾‍❤‍👨🏻 couple with heart: man, man, medium-dark skin tone, light skin tone + 👨🏾‍❤️‍👨🏼 couple with heart: man, man, medium-dark skin tone, medium-light skin tone + 👨🏾‍❤‍👨🏼 couple with heart: man, man, medium-dark skin tone, medium-light skin tone + 👨🏾‍❤️‍👨🏽 couple with heart: man, man, medium-dark skin tone, medium skin tone + 👨🏾‍❤‍👨🏽 couple with heart: man, man, medium-dark skin tone, medium skin tone + 👨🏾‍❤️‍👨🏾 couple with heart: man, man, medium-dark skin tone + 👨🏾‍❤‍👨🏾 couple with heart: man, man, medium-dark skin tone + 👨🏾‍❤️‍👨🏿 couple with heart: man, man, medium-dark skin tone, dark skin tone + 👨🏾‍❤‍👨🏿 couple with heart: man, man, medium-dark skin tone, dark skin tone + 👨🏿‍❤️‍👨🏻 couple with heart: man, man, dark skin tone, light skin tone + 👨🏿‍❤‍👨🏻 couple with heart: man, man, dark skin tone, light skin tone + 👨🏿‍❤️‍👨🏼 couple with heart: man, man, dark skin tone, medium-light skin tone + 👨🏿‍❤‍👨🏼 couple with heart: man, man, dark skin tone, medium-light skin tone + 👨🏿‍❤️‍👨🏽 couple with heart: man, man, dark skin tone, medium skin tone + 👨🏿‍❤‍👨🏽 couple with heart: man, man, dark skin tone, medium skin tone + 👨🏿‍❤️‍👨🏾 couple with heart: man, man, dark skin tone, medium-dark skin tone + 👨🏿‍❤‍👨🏾 couple with heart: man, man, dark skin tone, medium-dark skin tone + 👨🏿‍❤️‍👨🏿 couple with heart: man, man, dark skin tone + 👨🏿‍❤‍👨🏿 couple with heart: man, man, dark skin tone + 👩‍❤️‍👩 couple with heart: woman, woman + 👩‍❤‍👩 couple with heart: woman, woman + 👩🏻‍❤️‍👩🏻 couple with heart: woman, woman, light skin tone + 👩🏻‍❤‍👩🏻 couple with heart: woman, woman, light skin tone + 👩🏻‍❤️‍👩🏼 couple with heart: woman, woman, light skin tone, medium-light skin tone + 👩🏻‍❤‍👩🏼 couple with heart: woman, woman, light skin tone, medium-light skin tone + 👩🏻‍❤️‍👩🏽 couple with heart: woman, woman, light skin tone, medium skin tone + 👩🏻‍❤‍👩🏽 couple with heart: woman, woman, light skin tone, medium skin tone + 👩🏻‍❤️‍👩🏾 couple with heart: woman, woman, light skin tone, medium-dark skin tone + 👩🏻‍❤‍👩🏾 couple with heart: woman, woman, light skin tone, medium-dark skin tone + 👩🏻‍❤️‍👩🏿 couple with heart: woman, woman, light skin tone, dark skin tone + 👩🏻‍❤‍👩🏿 couple with heart: woman, woman, light skin tone, dark skin tone + 👩🏼‍❤️‍👩🏻 couple with heart: woman, woman, medium-light skin tone, light skin tone + 👩🏼‍❤‍👩🏻 couple with heart: woman, woman, medium-light skin tone, light skin tone + 👩🏼‍❤️‍👩🏼 couple with heart: woman, woman, medium-light skin tone + 👩🏼‍❤‍👩🏼 couple with heart: woman, woman, medium-light skin tone + 👩🏼‍❤️‍👩🏽 couple with heart: woman, woman, medium-light skin tone, medium skin tone + 👩🏼‍❤‍👩🏽 couple with heart: woman, woman, medium-light skin tone, medium skin tone + 👩🏼‍❤️‍👩🏾 couple with heart: woman, woman, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤‍👩🏾 couple with heart: woman, woman, medium-light skin tone, medium-dark skin tone + 👩🏼‍❤️‍👩🏿 couple with heart: woman, woman, medium-light skin tone, dark skin tone + 👩🏼‍❤‍👩🏿 couple with heart: woman, woman, medium-light skin tone, dark skin tone + 👩🏽‍❤️‍👩🏻 couple with heart: woman, woman, medium skin tone, light skin tone + 👩🏽‍❤‍👩🏻 couple with heart: woman, woman, medium skin tone, light skin tone + 👩🏽‍❤️‍👩🏼 couple with heart: woman, woman, medium skin tone, medium-light skin tone + 👩🏽‍❤‍👩🏼 couple with heart: woman, woman, medium skin tone, medium-light skin tone + 👩🏽‍❤️‍👩🏽 couple with heart: woman, woman, medium skin tone + 👩🏽‍❤‍👩🏽 couple with heart: woman, woman, medium skin tone + 👩🏽‍❤️‍👩🏾 couple with heart: woman, woman, medium skin tone, medium-dark skin tone + 👩🏽‍❤‍👩🏾 couple with heart: woman, woman, medium skin tone, medium-dark skin tone + 👩🏽‍❤️‍👩🏿 couple with heart: woman, woman, medium skin tone, dark skin tone + 👩🏽‍❤‍👩🏿 couple with heart: woman, woman, medium skin tone, dark skin tone + 👩🏾‍❤️‍👩🏻 couple with heart: woman, woman, medium-dark skin tone, light skin tone + 👩🏾‍❤‍👩🏻 couple with heart: woman, woman, medium-dark skin tone, light skin tone + 👩🏾‍❤️‍👩🏼 couple with heart: woman, woman, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤‍👩🏼 couple with heart: woman, woman, medium-dark skin tone, medium-light skin tone + 👩🏾‍❤️‍👩🏽 couple with heart: woman, woman, medium-dark skin tone, medium skin tone + 👩🏾‍❤‍👩🏽 couple with heart: woman, woman, medium-dark skin tone, medium skin tone + 👩🏾‍❤️‍👩🏾 couple with heart: woman, woman, medium-dark skin tone + 👩🏾‍❤‍👩🏾 couple with heart: woman, woman, medium-dark skin tone + 👩🏾‍❤️‍👩🏿 couple with heart: woman, woman, medium-dark skin tone, dark skin tone + 👩🏾‍❤‍👩🏿 couple with heart: woman, woman, medium-dark skin tone, dark skin tone + 👩🏿‍❤️‍👩🏻 couple with heart: woman, woman, dark skin tone, light skin tone + 👩🏿‍❤‍👩🏻 couple with heart: woman, woman, dark skin tone, light skin tone + 👩🏿‍❤️‍👩🏼 couple with heart: woman, woman, dark skin tone, medium-light skin tone + 👩🏿‍❤‍👩🏼 couple with heart: woman, woman, dark skin tone, medium-light skin tone + 👩🏿‍❤️‍👩🏽 couple with heart: woman, woman, dark skin tone, medium skin tone + 👩🏿‍❤‍👩🏽 couple with heart: woman, woman, dark skin tone, medium skin tone + 👩🏿‍❤️‍👩🏾 couple with heart: woman, woman, dark skin tone, medium-dark skin tone + 👩🏿‍❤‍👩🏾 couple with heart: woman, woman, dark skin tone, medium-dark skin tone + 👩🏿‍❤️‍👩🏿 couple with heart: woman, woman, dark skin tone + 👩🏿‍❤‍👩🏿 couple with heart: woman, woman, dark skin tone + 👪 family + 👨‍👩‍👦 family: man, woman, boy + 👨‍👩‍👧 family: man, woman, girl + 👨‍👩‍👧‍👦 family: man, woman, girl, boy + 👨‍👩‍👦‍👦 family: man, woman, boy, boy + 👨‍👩‍👧‍👧 family: man, woman, girl, girl + 👨‍👨‍👦 family: man, man, boy + 👨‍👨‍👧 family: man, man, girl + 👨‍👨‍👧‍👦 family: man, man, girl, boy + 👨‍👨‍👦‍👦 family: man, man, boy, boy + 👨‍👨‍👧‍👧 family: man, man, girl, girl + 👩‍👩‍👦 family: woman, woman, boy + 👩‍👩‍👧 family: woman, woman, girl + 👩‍👩‍👧‍👦 family: woman, woman, girl, boy + 👩‍👩‍👦‍👦 family: woman, woman, boy, boy + 👩‍👩‍👧‍👧 family: woman, woman, girl, girl + 👨‍👦 family: man, boy + 👨‍👦‍👦 family: man, boy, boy + 👨‍👧 family: man, girl + 👨‍👧‍👦 family: man, girl, boy + 👨‍👧‍👧 family: man, girl, girl + 👩‍👦 family: woman, boy + 👩‍👦‍👦 family: woman, boy, boy + 👩‍👧 family: woman, girl + 👩‍👧‍👦 family: woman, girl, boy + 👩‍👧‍👧 family: woman, girl, girl + 🗣️ speaking head + 🗣 speaking head + 👤 bust in silhouette + 👥 busts in silhouette + 🫂 people hugging + 👣 footprints + 🏻 light skin tone + 🏼 medium-light skin tone + 🏽 medium skin tone + 🏾 medium-dark skin tone + 🏿 dark skin tone + 🦰 red hair + 🦱 curly hair + 🦳 white hair + 🦲 bald + 🐵 monkey face + 🐒 monkey + 🦍 gorilla + 🦧 orangutan + 🐶 dog face + 🐕 dog + 🦮 guide dog + 🐕‍🦺 service dog + 🐩 poodle + 🐺 wolf + 🦊 fox + 🦝 raccoon + 🐱 cat face + 🐈 cat + 🐈‍⬛ black cat + 🦁 lion + 🐯 tiger face + 🐅 tiger + 🐆 leopard + 🐴 horse face + 🫎 moose + 🫏 donkey + 🐎 horse + 🦄 unicorn + 🦓 zebra + 🦌 deer + 🦬 bison + 🐮 cow face + 🐂 ox + 🐃 water buffalo + 🐄 cow + 🐷 pig face + 🐖 pig + 🐗 boar + 🐽 pig nose + 🐏 ram + 🐑 ewe + 🐐 goat + 🐪 camel + 🐫 two-hump camel + 🦙 llama + 🦒 giraffe + 🐘 elephant + 🦣 mammoth + 🦏 rhinoceros + 🦛 hippopotamus + 🐭 mouse face + 🐁 mouse + 🐀 rat + 🐹 hamster + 🐰 rabbit face + 🐇 rabbit + 🐿️ chipmunk + 🐿 chipmunk + 🦫 beaver + 🦔 hedgehog + 🦇 bat + 🐻 bear + 🐻‍❄️ polar bear + 🐻‍❄ polar bear + 🐨 koala + 🐼 panda + 🦥 sloth + 🦦 otter + 🦨 skunk + 🦘 kangaroo + 🦡 badger + 🐾 paw prints + 🦃 turkey + 🐔 chicken + 🐓 rooster + 🐣 hatching chick + 🐤 baby chick + 🐥 front-facing baby chick + 🐦 bird + 🐧 penguin + 🕊️ dove + 🕊 dove + 🦅 eagle + 🦆 duck + 🦢 swan + 🦉 owl + 🦤 dodo + 🪶 feather + 🦩 flamingo + 🦚 peacock + 🦜 parrot + 🪽 wing + 🐦‍⬛ black bird + 🪿 goose + 🐸 frog + 🐊 crocodile + 🐢 turtle + 🦎 lizard + 🐍 snake + 🐲 dragon face + 🐉 dragon + 🦕 sauropod + 🦖 T-Rex + 🐳 spouting whale + 🐋 whale + 🐬 dolphin + 🦭 seal + 🐟 fish + 🐠 tropical fish + 🐡 blowfish + 🦈 shark + 🐙 octopus + 🐚 spiral shell + 🪸 coral + 🪼 jellyfish + 🐌 snail + 🦋 butterfly + 🐛 bug + 🐜 ant + 🐝 honeybee + 🪲 beetle + 🐞 lady beetle + 🦗 cricket + 🪳 cockroach + 🕷️ spider + 🕷 spider + 🕸️ spider web + 🕸 spider web + 🦂 scorpion + 🦟 mosquito + 🪰 fly + 🪱 worm + 🦠 microbe + 💐 bouquet + 🌸 cherry blossom + 💮 white flower + 🪷 lotus + 🏵️ rosette + 🏵 rosette + 🌹 rose + 🥀 wilted flower + 🌺 hibiscus + 🌻 sunflower + 🌼 blossom + 🌷 tulip + 🪻 hyacinth + 🌱 seedling + 🪴 potted plant + 🌲 evergreen tree + 🌳 deciduous tree + 🌴 palm tree + 🌵 cactus + 🌾 sheaf of rice + 🌿 herb + ☘️ shamrock + ☘ shamrock + 🍀 four leaf clover + 🍁 maple leaf + 🍂 fallen leaf + 🍃 leaf fluttering in wind + 🪹 empty nest + 🪺 nest with eggs + 🍄 mushroom + 🍇 grapes + 🍈 melon + 🍉 watermelon + 🍊 tangerine + 🍋 lemon + 🍌 banana + 🍍 pineapple + 🥭 mango + 🍎 red apple + 🍏 green apple + 🍐 pear + 🍑 peach + 🍒 cherries + 🍓 strawberry + 🫐 blueberries + 🥝 kiwi fruit + 🍅 tomato + 🫒 olive + 🥥 coconut + 🥑 avocado + 🍆 eggplant + 🥔 potato + 🥕 carrot + 🌽 ear of corn + 🌶️ hot pepper + 🌶 hot pepper + 🫑 bell pepper + 🥒 cucumber + 🥬 leafy green + 🥦 broccoli + 🧄 garlic + 🧅 onion + 🥜 peanuts + 🫘 beans + 🌰 chestnut + 🫚 ginger root + 🫛 pea pod + 🍞 bread + 🥐 croissant + 🥖 baguette bread + 🫓 flatbread + 🥨 pretzel + 🥯 bagel + 🥞 pancakes + 🧇 waffle + 🧀 cheese wedge + 🍖 meat on bone + 🍗 poultry leg + 🥩 cut of meat + 🥓 bacon + 🍔 hamburger + 🍟 french fries + 🍕 pizza + 🌭 hot dog + 🥪 sandwich + 🌮 taco + 🌯 burrito + 🫔 tamale + 🥙 stuffed flatbread + 🧆 falafel + 🥚 egg + 🍳 cooking + 🥘 shallow pan of food + 🍲 pot of food + 🫕 fondue + 🥣 bowl with spoon + 🥗 green salad + 🍿 popcorn + 🧈 butter + 🧂 salt + 🥫 canned food + 🍱 bento box + 🍘 rice cracker + 🍙 rice ball + 🍚 cooked rice + 🍛 curry rice + 🍜 steaming bowl + 🍝 spaghetti + 🍠 roasted sweet potato + 🍢 oden + 🍣 sushi + 🍤 fried shrimp + 🍥 fish cake with swirl + 🥮 moon cake + 🍡 dango + 🥟 dumpling + 🥠 fortune cookie + 🥡 takeout box + 🦀 crab + 🦞 lobster + 🦐 shrimp + 🦑 squid + 🦪 oyster + 🍦 soft ice cream + 🍧 shaved ice + 🍨 ice cream + 🍩 doughnut + 🍪 cookie + 🎂 birthday cake + 🍰 shortcake + 🧁 cupcake + 🥧 pie + 🍫 chocolate bar + 🍬 candy + 🍭 lollipop + 🍮 custard + 🍯 honey pot + 🍼 baby bottle + 🥛 glass of milk + ☕ hot beverage + 🫖 teapot + 🍵 teacup without handle + 🍶 sake + 🍾 bottle with popping cork + 🍷 wine glass + 🍸 cocktail glass + 🍹 tropical drink + 🍺 beer mug + 🍻 clinking beer mugs + 🥂 clinking glasses + 🥃 tumbler glass + 🫗 pouring liquid + 🥤 cup with straw + 🧋 bubble tea + 🧃 beverage box + 🧉 mate + 🧊 ice + 🥢 chopsticks + 🍽️ fork and knife with plate + 🍽 fork and knife with plate + 🍴 fork and knife + 🥄 spoon + 🔪 kitchen knife + 🫙 jar + 🏺 amphora + 🌍 globe showing Europe-Africa + 🌎 globe showing Americas + 🌏 globe showing Asia-Australia + 🌐 globe with meridians + 🗺️ world map + 🗺 world map + 🗾 map of Japan + 🧭 compass + 🏔️ snow-capped mountain + 🏔 snow-capped mountain + ⛰️ mountain + ⛰ mountain + 🌋 volcano + 🗻 mount fuji + 🏕️ camping + 🏕 camping + 🏖️ beach with umbrella + 🏖 beach with umbrella + 🏜️ desert + 🏜 desert + 🏝️ desert island + 🏝 desert island + 🏞️ national park + 🏞 national park + 🏟️ stadium + 🏟 stadium + 🏛️ classical building + 🏛 classical building + 🏗️ building construction + 🏗 building construction + 🧱 brick + 🪨 rock + 🪵 wood + 🛖 hut + 🏘️ houses + 🏘 houses + 🏚️ derelict house + 🏚 derelict house + 🏠 house + 🏡 house with garden + 🏢 office building + 🏣 Japanese post office + 🏤 post office + 🏥 hospital + 🏦 bank + 🏨 hotel + 🏩 love hotel + 🏪 convenience store + 🏫 school + 🏬 department store + 🏭 factory + 🏯 Japanese castle + 🏰 castle + 💒 wedding + 🗼 Tokyo tower + 🗽 Statue of Liberty + ⛪ church + 🕌 mosque + 🛕 hindu temple + 🕍 synagogue + ⛩️ shinto shrine + ⛩ shinto shrine + 🕋 kaaba + ⛲ fountain + ⛺ tent + 🌁 foggy + 🌃 night with stars + 🏙️ cityscape + 🏙 cityscape + 🌄 sunrise over mountains + 🌅 sunrise + 🌆 cityscape at dusk + 🌇 sunset + 🌉 bridge at night + ♨️ hot springs + ♨ hot springs + 🎠 carousel horse + 🛝 playground slide + 🎡 ferris wheel + 🎢 roller coaster + 💈 barber pole + 🎪 circus tent + 🚂 locomotive + 🚃 railway car + 🚄 high-speed train + 🚅 bullet train + 🚆 train + 🚇 metro + 🚈 light rail + 🚉 station + 🚊 tram + 🚝 monorail + 🚞 mountain railway + 🚋 tram car + 🚌 bus + 🚍 oncoming bus + 🚎 trolleybus + 🚐 minibus + 🚑 ambulance + 🚒 fire engine + 🚓 police car + 🚔 oncoming police car + 🚕 taxi + 🚖 oncoming taxi + 🚗 automobile + 🚘 oncoming automobile + 🚙 sport utility vehicle + 🛻 pickup truck + 🚚 delivery truck + 🚛 articulated lorry + 🚜 tractor + 🏎️ racing car + 🏎 racing car + 🏍️ motorcycle + 🏍 motorcycle + 🛵 motor scooter + 🦽 manual wheelchair + 🦼 motorized wheelchair + 🛺 auto rickshaw + 🚲 bicycle + 🛴 kick scooter + 🛹 skateboard + 🛼 roller skate + 🚏 bus stop + 🛣️ motorway + 🛣 motorway + 🛤️ railway track + 🛤 railway track + 🛢️ oil drum + 🛢 oil drum + ⛽ fuel pump + 🛞 wheel + 🚨 police car light + 🚥 horizontal traffic light + 🚦 vertical traffic light + 🛑 stop sign + 🚧 construction + ⚓ anchor + 🛟 ring buoy + ⛵ sailboat + 🛶 canoe + 🚤 speedboat + 🛳️ passenger ship + 🛳 passenger ship + ⛴️ ferry + ⛴ ferry + 🛥️ motor boat + 🛥 motor boat + 🚢 ship + ✈️ airplane + ✈ airplane + 🛩️ small airplane + 🛩 small airplane + 🛫 airplane departure + 🛬 airplane arrival + 🪂 parachute + 💺 seat + 🚁 helicopter + 🚟 suspension railway + 🚠 mountain cableway + 🚡 aerial tramway + 🛰️ satellite + 🛰 satellite + 🚀 rocket + 🛸 flying saucer + 🛎️ bellhop bell + 🛎 bellhop bell + 🧳 luggage + ⌛ hourglass done + ⏳ hourglass not done + ⌚ watch + ⏰ alarm clock + ⏱️ stopwatch + ⏱ stopwatch + ⏲️ timer clock + ⏲ timer clock + 🕰️ mantelpiece clock + 🕰 mantelpiece clock + 🕛 twelve o’clock + 🕧 twelve-thirty + 🕐 one o’clock + 🕜 one-thirty + 🕑 two o’clock + 🕝 two-thirty + 🕒 three o’clock + 🕞 three-thirty + 🕓 four o’clock + 🕟 four-thirty + 🕔 five o’clock + 🕠 five-thirty + 🕕 six o’clock + 🕡 six-thirty + 🕖 seven o’clock + 🕢 seven-thirty + 🕗 eight o’clock + 🕣 eight-thirty + 🕘 nine o’clock + 🕤 nine-thirty + 🕙 ten o’clock + 🕥 ten-thirty + 🕚 eleven o’clock + 🕦 eleven-thirty + 🌑 new moon + 🌒 waxing crescent moon + 🌓 first quarter moon + 🌔 waxing gibbous moon + 🌕 full moon + 🌖 waning gibbous moon + 🌗 last quarter moon + 🌘 waning crescent moon + 🌙 crescent moon + 🌚 new moon face + 🌛 first quarter moon face + 🌜 last quarter moon face + 🌡️ thermometer + 🌡 thermometer + ☀️ sun + ☀ sun + 🌝 full moon face + 🌞 sun with face + 🪐 ringed planet + ⭐ star + 🌟 glowing star + 🌠 shooting star + 🌌 milky way + ☁️ cloud + ☁ cloud + ⛅ sun behind cloud + ⛈️ cloud with lightning and rain + ⛈ cloud with lightning and rain + 🌤️ sun behind small cloud + 🌤 sun behind small cloud + 🌥️ sun behind large cloud + 🌥 sun behind large cloud + 🌦️ sun behind rain cloud + 🌦 sun behind rain cloud + 🌧️ cloud with rain + 🌧 cloud with rain + 🌨️ cloud with snow + 🌨 cloud with snow + 🌩️ cloud with lightning + 🌩 cloud with lightning + 🌪️ tornado + 🌪 tornado + 🌫️ fog + 🌫 fog + 🌬️ wind face + 🌬 wind face + 🌀 cyclone + 🌈 rainbow + 🌂 closed umbrella + ☂️ umbrella + ☂ umbrella + ☔ umbrella with rain drops + ⛱️ umbrella on ground + ⛱ umbrella on ground + ⚡ high voltage + ❄️ snowflake + ❄ snowflake + ☃️ snowman + ☃ snowman + ⛄ snowman without snow + ☄️ comet + ☄ comet + 🔥 fire + 💧 droplet + 🌊 water wave + 🎃 jack-o-lantern + 🎄 Christmas tree + 🎆 fireworks + 🎇 sparkler + 🧨 firecracker + ✨ sparkles + 🎈 balloon + 🎉 party popper + 🎊 confetti ball + 🎋 tanabata tree + 🎍 pine decoration + 🎎 Japanese dolls + 🎏 carp streamer + 🎐 wind chime + 🎑 moon viewing ceremony + 🧧 red envelope + 🎀 ribbon + 🎁 wrapped gift + 🎗️ reminder ribbon + 🎗 reminder ribbon + 🎟️ admission tickets + 🎟 admission tickets + 🎫 ticket + 🎖️ military medal + 🎖 military medal + 🏆 trophy + 🏅 sports medal + 🥇 1st place medal + 🥈 2nd place medal + 🥉 3rd place medal + ⚽ soccer ball + ⚾ baseball + 🥎 softball + 🏀 basketball + 🏐 volleyball + 🏈 american football + 🏉 rugby football + 🎾 tennis + 🥏 flying disc + 🎳 bowling + 🏏 cricket game + 🏑 field hockey + 🏒 ice hockey + 🥍 lacrosse + 🏓 ping pong + 🏸 badminton + 🥊 boxing glove + 🥋 martial arts uniform + 🥅 goal net + ⛳ flag in hole + ⛸️ ice skate + ⛸ ice skate + 🎣 fishing pole + 🤿 diving mask + 🎽 running shirt + 🎿 skis + 🛷 sled + 🥌 curling stone + 🎯 bullseye + 🪀 yo-yo + 🪁 kite + 🔫 water pistol + 🎱 pool 8 ball + 🔮 crystal ball + 🪄 magic wand + 🎮 video game + 🕹️ joystick + 🕹 joystick + 🎰 slot machine + 🎲 game die + 🧩 puzzle piece + 🧸 teddy bear + 🪅 piñata + 🪩 mirror ball + 🪆 nesting dolls + ♠️ spade suit + ♠ spade suit + ♥️ heart suit + ♥ heart suit + ♦️ diamond suit + ♦ diamond suit + ♣️ club suit + ♣ club suit + ♟️ chess pawn + ♟ chess pawn + 🃏 joker + 🀄 mahjong red dragon + 🎴 flower playing cards + 🎭 performing arts + 🖼️ framed picture + 🖼 framed picture + 🎨 artist palette + 🧵 thread + 🪡 sewing needle + 🧶 yarn + 🪢 knot + 👓 glasses + 🕶️ sunglasses + 🕶 sunglasses + 🥽 goggles + 🥼 lab coat + 🦺 safety vest + 👔 necktie + 👕 t-shirt + 👖 jeans + 🧣 scarf + 🧤 gloves + 🧥 coat + 🧦 socks + 👗 dress + 👘 kimono + 🥻 sari + 🩱 one-piece swimsuit + 🩲 briefs + 🩳 shorts + 👙 bikini + 👚 woman’s clothes + 🪭 folding hand fan + 👛 purse + 👜 handbag + 👝 clutch bag + 🛍️ shopping bags + 🛍 shopping bags + 🎒 backpack + 🩴 thong sandal + 👞 man’s shoe + 👟 running shoe + 🥾 hiking boot + 🥿 flat shoe + 👠 high-heeled shoe + 👡 woman’s sandal + 🩰 ballet shoes + 👢 woman’s boot + 🪮 hair pick + 👑 crown + 👒 woman’s hat + 🎩 top hat + 🎓 graduation cap + 🧢 billed cap + 🪖 military helmet + ⛑️ rescue worker’s helmet + ⛑ rescue worker’s helmet + 📿 prayer beads + 💄 lipstick + 💍 ring + 💎 gem stone + 🔇 muted speaker + 🔈 speaker low volume + 🔉 speaker medium volume + 🔊 speaker high volume + 📢 loudspeaker + 📣 megaphone + 📯 postal horn + 🔔 bell + 🔕 bell with slash + 🎼 musical score + 🎵 musical note + 🎶 musical notes + 🎙️ studio microphone + 🎙 studio microphone + 🎚️ level slider + 🎚 level slider + 🎛️ control knobs + 🎛 control knobs + 🎤 microphone + 🎧 headphone + 📻 radio + 🎷 saxophone + 🪗 accordion + 🎸 guitar + 🎹 musical keyboard + 🎺 trumpet + 🎻 violin + 🪕 banjo + 🥁 drum + 🪘 long drum + 🪇 maracas + 🪈 flute + 📱 mobile phone + 📲 mobile phone with arrow + ☎️ telephone + ☎ telephone + 📞 telephone receiver + 📟 pager + 📠 fax machine + 🔋 battery + 🪫 low battery + 🔌 electric plug + 💻 laptop + 🖥️ desktop computer + 🖥 desktop computer + 🖨️ printer + 🖨 printer + ⌨️ keyboard + ⌨ keyboard + 🖱️ computer mouse + 🖱 computer mouse + 🖲️ trackball + 🖲 trackball + 💽 computer disk + 💾 floppy disk + 💿 optical disk + 📀 dvd + 🧮 abacus + 🎥 movie camera + 🎞️ film frames + 🎞 film frames + 📽️ film projector + 📽 film projector + 🎬 clapper board + 📺 television + 📷 camera + 📸 camera with flash + 📹 video camera + 📼 videocassette + 🔍 magnifying glass tilted left + 🔎 magnifying glass tilted right + 🕯️ candle + 🕯 candle + 💡 light bulb + 🔦 flashlight + 🏮 red paper lantern + 🪔 diya lamp + 📔 notebook with decorative cover + 📕 closed book + 📖 open book + 📗 green book + 📘 blue book + 📙 orange book + 📚 books + 📓 notebook + 📒 ledger + 📃 page with curl + 📜 scroll + 📄 page facing up + 📰 newspaper + 🗞️ rolled-up newspaper + 🗞 rolled-up newspaper + 📑 bookmark tabs + 🔖 bookmark + 🏷️ label + 🏷 label + 💰 money bag + 🪙 coin + 💴 yen banknote + 💵 dollar banknote + 💶 euro banknote + 💷 pound banknote + 💸 money with wings + 💳 credit card + 🧾 receipt + 💹 chart increasing with yen + ✉️ envelope + ✉ envelope + 📧 e-mail + 📨 incoming envelope + 📩 envelope with arrow + 📤 outbox tray + 📥 inbox tray + 📦 package + 📫 closed mailbox with raised flag + 📪 closed mailbox with lowered flag + 📬 open mailbox with raised flag + 📭 open mailbox with lowered flag + 📮 postbox + 🗳️ ballot box with ballot + 🗳 ballot box with ballot + ✏️ pencil + ✏ pencil + ✒️ black nib + ✒ black nib + 🖋️ fountain pen + 🖋 fountain pen + 🖊️ pen + 🖊 pen + 🖌️ paintbrush + 🖌 paintbrush + 🖍️ crayon + 🖍 crayon + 📝 memo + 💼 briefcase + 📁 file folder + 📂 open file folder + 🗂️ card index dividers + 🗂 card index dividers + 📅 calendar + 📆 tear-off calendar + 🗒️ spiral notepad + 🗒 spiral notepad + 🗓️ spiral calendar + 🗓 spiral calendar + 📇 card index + 📈 chart increasing + 📉 chart decreasing + 📊 bar chart + 📋 clipboard + 📌 pushpin + 📍 round pushpin + 📎 paperclip + 🖇️ linked paperclips + 🖇 linked paperclips + 📏 straight ruler + 📐 triangular ruler + ✂️ scissors + ✂ scissors + 🗃️ card file box + 🗃 card file box + 🗄️ file cabinet + 🗄 file cabinet + 🗑️ wastebasket + 🗑 wastebasket + 🔒 locked + 🔓 unlocked + 🔏 locked with pen + 🔐 locked with key + 🔑 key + 🗝️ old key + 🗝 old key + 🔨 hammer + 🪓 axe + ⛏️ pick + ⛏ pick + ⚒️ hammer and pick + ⚒ hammer and pick + 🛠️ hammer and wrench + 🛠 hammer and wrench + 🗡️ dagger + 🗡 dagger + ⚔️ crossed swords + ⚔ crossed swords + 💣 bomb + 🪃 boomerang + 🏹 bow and arrow + 🛡️ shield + 🛡 shield + 🪚 carpentry saw + 🔧 wrench + 🪛 screwdriver + 🔩 nut and bolt + ⚙️ gear + ⚙ gear + 🗜️ clamp + 🗜 clamp + ⚖️ balance scale + ⚖ balance scale + 🦯 white cane + 🔗 link + ⛓️ chains + ⛓ chains + 🪝 hook + 🧰 toolbox + 🧲 magnet + 🪜 ladder + ⚗️ alembic + ⚗ alembic + 🧪 test tube + 🧫 petri dish + 🧬 dna + 🔬 microscope + 🔭 telescope + 📡 satellite antenna + 💉 syringe + 🩸 drop of blood + 💊 pill + 🩹 adhesive bandage + 🩼 crutch + 🩺 stethoscope + 🩻 x-ray + 🚪 door + 🛗 elevator + 🪞 mirror + 🪟 window + 🛏️ bed + 🛏 bed + 🛋️ couch and lamp + 🛋 couch and lamp + 🪑 chair + 🚽 toilet + 🪠 plunger + 🚿 shower + 🛁 bathtub + 🪤 mouse trap + 🪒 razor + 🧴 lotion bottle + 🧷 safety pin + 🧹 broom + 🧺 basket + 🧻 roll of paper + 🪣 bucket + 🧼 soap + 🫧 bubbles + 🪥 toothbrush + 🧽 sponge + 🧯 fire extinguisher + 🛒 shopping cart + 🚬 cigarette + ⚰️ coffin + ⚰ coffin + 🪦 headstone + ⚱️ funeral urn + ⚱ funeral urn + 🧿 nazar amulet + 🪬 hamsa + 🗿 moai + 🪧 placard + 🪪 identification card + 🏧 ATM sign + 🚮 litter in bin sign + 🚰 potable water + ♿ wheelchair symbol + 🚹 men’s room + 🚺 women’s room + 🚻 restroom + 🚼 baby symbol + 🚾 water closet + 🛂 passport control + 🛃 customs + 🛄 baggage claim + 🛅 left luggage + ⚠️ warning + ⚠ warning + 🚸 children crossing + ⛔ no entry + 🚫 prohibited + 🚳 no bicycles + 🚭 no smoking + 🚯 no littering + 🚱 non-potable water + 🚷 no pedestrians + 📵 no mobile phones + 🔞 no one under eighteen + ☢️ radioactive + ☢ radioactive + ☣️ biohazard + ☣ biohazard + ⬆️ up arrow + ⬆ up arrow + ↗️ up-right arrow + ↗ up-right arrow + ➡️ right arrow + ➡ right arrow + ↘️ down-right arrow + ↘ down-right arrow + ⬇️ down arrow + ⬇ down arrow + ↙️ down-left arrow + ↙ down-left arrow + ⬅️ left arrow + ⬅ left arrow + ↖️ up-left arrow + ↖ up-left arrow + ↕️ up-down arrow + ↕ up-down arrow + ↔️ left-right arrow + ↔ left-right arrow + ↩️ right arrow curving left + ↩ right arrow curving left + ↪️ left arrow curving right + ↪ left arrow curving right + ⤴️ right arrow curving up + ⤴ right arrow curving up + ⤵️ right arrow curving down + ⤵ right arrow curving down + 🔃 clockwise vertical arrows + 🔄 counterclockwise arrows button + 🔙 BACK arrow + 🔚 END arrow + 🔛 ON! arrow + 🔜 SOON arrow + 🔝 TOP arrow + 🛐 place of worship + ⚛️ atom symbol + ⚛ atom symbol + 🕉️ om + 🕉 om + ✡️ star of David + ✡ star of David + ☸️ wheel of dharma + ☸ wheel of dharma + ☯️ yin yang + ☯ yin yang + ✝️ latin cross + ✝ latin cross + ☦️ orthodox cross + ☦ orthodox cross + ☪️ star and crescent + ☪ star and crescent + ☮️ peace symbol + ☮ peace symbol + 🕎 menorah + 🔯 dotted six-pointed star + 🪯 khanda + ♈ Aries + ♉ Taurus + ♊ Gemini + ♋ Cancer + ♌ Leo + ♍ Virgo + ♎ Libra + ♏ Scorpio + ♐ Sagittarius + ♑ Capricorn + ♒ Aquarius + ♓ Pisces + ⛎ Ophiuchus + 🔀 shuffle tracks button + 🔁 repeat button + 🔂 repeat single button + ▶️ play button + ▶ play button + ⏩ fast-forward button + ⏭️ next track button + ⏭ next track button + ⏯️ play or pause button + ⏯ play or pause button + ◀️ reverse button + ◀ reverse button + ⏪ fast reverse button + ⏮️ last track button + ⏮ last track button + 🔼 upwards button + ⏫ fast up button + 🔽 downwards button + ⏬ fast down button + ⏸️ pause button + ⏸ pause button + ⏹️ stop button + ⏹ stop button + ⏺️ record button + ⏺ record button + ⏏️ eject button + ⏏ eject button + 🎦 cinema + 🔅 dim button + 🔆 bright button + 📶 antenna bars + 🛜 wireless + 📳 vibration mode + 📴 mobile phone off + ♀️ female sign + ♀ female sign + ♂️ male sign + ♂ male sign + ⚧️ transgender symbol + ⚧ transgender symbol + ✖️ multiply + ✖ multiply + ➕ plus + ➖ minus + ➗ divide + 🟰 heavy equals sign + ♾️ infinity + ♾ infinity + ‼️ double exclamation mark + ‼ double exclamation mark + ⁉️ exclamation question mark + ⁉ exclamation question mark + ❓ red question mark + ❔ white question mark + ❕ white exclamation mark + ❗ red exclamation mark + 〰️ wavy dash + 〰 wavy dash + 💱 currency exchange + 💲 heavy dollar sign + ⚕️ medical symbol + ⚕ medical symbol + ♻️ recycling symbol + ♻ recycling symbol + ⚜️ fleur-de-lis + ⚜ fleur-de-lis + 🔱 trident emblem + 📛 name badge + 🔰 Japanese symbol for beginner + ⭕ hollow red circle + ✅ check mark button + ☑️ check box with check + ☑ check box with check + ✔️ check mark + ✔ check mark + ❌ cross mark + ❎ cross mark button + ➰ curly loop + ➿ double curly loop + 〽️ part alternation mark + 〽 part alternation mark + ✳️ eight-spoked asterisk + ✳ eight-spoked asterisk + ✴️ eight-pointed star + ✴ eight-pointed star + ❇️ sparkle + ❇ sparkle + ©️ copyright + © copyright + ®️ registered + ® registered + ™️ trade mark + ™ trade mark + #️⃣ keycap: # + #⃣ keycap: # + *️⃣ keycap: * + *⃣ keycap: * + 0️⃣ keycap: 0 + 0⃣ keycap: 0 + 1️⃣ keycap: 1 + 1⃣ keycap: 1 + 2️⃣ keycap: 2 + 2⃣ keycap: 2 + 3️⃣ keycap: 3 + 3⃣ keycap: 3 + 4️⃣ keycap: 4 + 4⃣ keycap: 4 + 5️⃣ keycap: 5 + 5⃣ keycap: 5 + 6️⃣ keycap: 6 + 6⃣ keycap: 6 + 7️⃣ keycap: 7 + 7⃣ keycap: 7 + 8️⃣ keycap: 8 + 8⃣ keycap: 8 + 9️⃣ keycap: 9 + 9⃣ keycap: 9 + 🔟 keycap: 10 + 🔠 input latin uppercase + 🔡 input latin lowercase + 🔢 input numbers + 🔣 input symbols + 🔤 input latin letters + 🅰️ A button (blood type) + 🅰 A button (blood type) + 🆎 AB button (blood type) + 🅱️ B button (blood type) + 🅱 B button (blood type) + 🆑 CL button + 🆒 COOL button + 🆓 FREE button + ℹ️ information + ℹ information + 🆔 ID button + Ⓜ️ circled M + Ⓜ circled M + 🆕 NEW button + 🆖 NG button + 🅾️ O button (blood type) + 🅾 O button (blood type) + 🆗 OK button + 🅿️ P button + 🅿 P button + 🆘 SOS button + 🆙 UP! button + 🆚 VS button + 🈁 Japanese “here” button + 🈂️ Japanese “service charge” button + 🈂 Japanese “service charge” button + 🈷️ Japanese “monthly amount” button + 🈷 Japanese “monthly amount” button + 🈶 Japanese “not free of charge” button + 🈯 Japanese “reserved” button + 🉐 Japanese “bargain” button + 🈹 Japanese “discount” button + 🈚 Japanese “free of charge” button + 🈲 Japanese “prohibited” button + 🉑 Japanese “acceptable” button + 🈸 Japanese “application” button + 🈴 Japanese “passing grade” button + 🈳 Japanese “vacancy” button + ㊗️ Japanese “congratulations” button + ㊗ Japanese “congratulations” button + ㊙️ Japanese “secret” button + ㊙ Japanese “secret” button + 🈺 Japanese “open for business” button + 🈵 Japanese “no vacancy” button + 🔴 red circle + 🟠 orange circle + 🟡 yellow circle + 🟢 green circle + 🔵 blue circle + 🟣 purple circle + 🟤 brown circle + ⚫ black circle + ⚪ white circle + 🟥 red square + 🟧 orange square + 🟨 yellow square + 🟩 green square + 🟦 blue square + 🟪 purple square + 🟫 brown square + ⬛ black large square + ⬜ white large square + ◼️ black medium square + ◼ black medium square + ◻️ white medium square + ◻ white medium square + ◾ black medium-small square + ◽ white medium-small square + ▪️ black small square + ▪ black small square + ▫️ white small square + ▫ white small square + 🔶 large orange diamond + 🔷 large blue diamond + 🔸 small orange diamond + 🔹 small blue diamond + 🔺 red triangle pointed up + 🔻 red triangle pointed down + 💠 diamond with a dot + 🔘 radio button + 🔳 white square button + 🔲 black square button + 🏁 chequered flag + 🚩 triangular flag + 🎌 crossed flags + 🏴 black flag + 🏳️ white flag + 🏳 white flag + 🏳️‍🌈 rainbow flag + 🏳‍🌈 rainbow flag + 🏳️‍⚧️ transgender flag + 🏳‍⚧️ transgender flag + 🏳️‍⚧ transgender flag + 🏳‍⚧ transgender flag + 🏴‍☠️ pirate flag + 🏴‍☠ pirate flag + 🇦🇨 flag: Ascension Island + 🇦🇩 flag: Andorra + 🇦🇪 flag: United Arab Emirates + 🇦🇫 flag: Afghanistan + 🇦🇬 flag: Antigua & Barbuda + 🇦🇮 flag: Anguilla + 🇦🇱 flag: Albania + 🇦🇲 flag: Armenia + 🇦🇴 flag: Angola + 🇦🇶 flag: Antarctica + 🇦🇷 flag: Argentina + 🇦🇸 flag: American Samoa + 🇦🇹 flag: Austria + 🇦🇺 flag: Australia + 🇦🇼 flag: Aruba + 🇦🇽 flag: Åland Islands + 🇦🇿 flag: Azerbaijan + 🇧🇦 flag: Bosnia & Herzegovina + 🇧🇧 flag: Barbados + 🇧🇩 flag: Bangladesh + 🇧🇪 flag: Belgium + 🇧🇫 flag: Burkina Faso + 🇧🇬 flag: Bulgaria + 🇧🇭 flag: Bahrain + 🇧🇮 flag: Burundi + 🇧🇯 flag: Benin + 🇧🇱 flag: St. Barthélemy + 🇧🇲 flag: Bermuda + 🇧🇳 flag: Brunei + 🇧🇴 flag: Bolivia + 🇧🇶 flag: Caribbean Netherlands + 🇧🇷 flag: Brazil + 🇧🇸 flag: Bahamas + 🇧🇹 flag: Bhutan + 🇧🇻 flag: Bouvet Island + 🇧🇼 flag: Botswana + 🇧🇾 flag: Belarus + 🇧🇿 flag: Belize + 🇨🇦 flag: Canada + 🇨🇨 flag: Cocos (Keeling) Islands + 🇨🇩 flag: Congo - Kinshasa + 🇨🇫 flag: Central African Republic + 🇨🇬 flag: Congo - Brazzaville + 🇨🇭 flag: Switzerland + 🇨🇮 flag: Côte d’Ivoire + 🇨🇰 flag: Cook Islands + 🇨🇱 flag: Chile + 🇨🇲 flag: Cameroon + 🇨🇳 flag: China + 🇨🇴 flag: Colombia + 🇨🇵 flag: Clipperton Island + 🇨🇷 flag: Costa Rica + 🇨🇺 flag: Cuba + 🇨🇻 flag: Cape Verde + 🇨🇼 flag: Curaçao + 🇨🇽 flag: Christmas Island + 🇨🇾 flag: Cyprus + 🇨🇿 flag: Czechia + 🇩🇪 flag: Germany + 🇩🇬 flag: Diego Garcia + 🇩🇯 flag: Djibouti + 🇩🇰 flag: Denmark + 🇩🇲 flag: Dominica + 🇩🇴 flag: Dominican Republic + 🇩🇿 flag: Algeria + 🇪🇦 flag: Ceuta & Melilla + 🇪🇨 flag: Ecuador + 🇪🇪 flag: Estonia + 🇪🇬 flag: Egypt + 🇪🇭 flag: Western Sahara + 🇪🇷 flag: Eritrea + 🇪🇸 flag: Spain + 🇪🇹 flag: Ethiopia + 🇪🇺 flag: European Union + 🇫🇮 flag: Finland + 🇫🇯 flag: Fiji + 🇫🇰 flag: Falkland Islands + 🇫🇲 flag: Micronesia + 🇫🇴 flag: Faroe Islands + 🇫🇷 flag: France + 🇬🇦 flag: Gabon + 🇬🇧 flag: United Kingdom + 🇬🇩 flag: Grenada + 🇬🇪 flag: Georgia + 🇬🇫 flag: French Guiana + 🇬🇬 flag: Guernsey + 🇬🇭 flag: Ghana + 🇬🇮 flag: Gibraltar + 🇬🇱 flag: Greenland + 🇬🇲 flag: Gambia + 🇬🇳 flag: Guinea + 🇬🇵 flag: Guadeloupe + 🇬🇶 flag: Equatorial Guinea + 🇬🇷 flag: Greece + 🇬🇸 flag: South Georgia & South Sandwich Islands + 🇬🇹 flag: Guatemala + 🇬🇺 flag: Guam + 🇬🇼 flag: Guinea-Bissau + 🇬🇾 flag: Guyana + 🇭🇰 flag: Hong Kong SAR China + 🇭🇲 flag: Heard & McDonald Islands + 🇭🇳 flag: Honduras + 🇭🇷 flag: Croatia + 🇭🇹 flag: Haiti + 🇭🇺 flag: Hungary + 🇮🇨 flag: Canary Islands + 🇮🇩 flag: Indonesia + 🇮🇪 flag: Ireland + 🇮🇱 flag: Israel + 🇮🇲 flag: Isle of Man + 🇮🇳 flag: India + 🇮🇴 flag: British Indian Ocean Territory + 🇮🇶 flag: Iraq + 🇮🇷 flag: Iran + 🇮🇸 flag: Iceland + 🇮🇹 flag: Italy + 🇯🇪 flag: Jersey + 🇯🇲 flag: Jamaica + 🇯🇴 flag: Jordan + 🇯🇵 flag: Japan + 🇰🇪 flag: Kenya + 🇰🇬 flag: Kyrgyzstan + 🇰🇭 flag: Cambodia + 🇰🇮 flag: Kiribati + 🇰🇲 flag: Comoros + 🇰🇳 flag: St. Kitts & Nevis + 🇰🇵 flag: North Korea + 🇰🇷 flag: South Korea + 🇰🇼 flag: Kuwait + 🇰🇾 flag: Cayman Islands + 🇰🇿 flag: Kazakhstan + 🇱🇦 flag: Laos + 🇱🇧 flag: Lebanon + 🇱🇨 flag: St. Lucia + 🇱🇮 flag: Liechtenstein + 🇱🇰 flag: Sri Lanka + 🇱🇷 flag: Liberia + 🇱🇸 flag: Lesotho + 🇱🇹 flag: Lithuania + 🇱🇺 flag: Luxembourg + 🇱🇻 flag: Latvia + 🇱🇾 flag: Libya + 🇲🇦 flag: Morocco + 🇲🇨 flag: Monaco + 🇲🇩 flag: Moldova + 🇲🇪 flag: Montenegro + 🇲🇫 flag: St. Martin + 🇲🇬 flag: Madagascar + 🇲🇭 flag: Marshall Islands + 🇲🇰 flag: North Macedonia + 🇲🇱 flag: Mali + 🇲🇲 flag: Myanmar (Burma) + 🇲🇳 flag: Mongolia + 🇲🇴 flag: Macao SAR China + 🇲🇵 flag: Northern Mariana Islands + 🇲🇶 flag: Martinique + 🇲🇷 flag: Mauritania + 🇲🇸 flag: Montserrat + 🇲🇹 flag: Malta + 🇲🇺 flag: Mauritius + 🇲🇻 flag: Maldives + 🇲🇼 flag: Malawi + 🇲🇽 flag: Mexico + 🇲🇾 flag: Malaysia + 🇲🇿 flag: Mozambique + 🇳🇦 flag: Namibia + 🇳🇨 flag: New Caledonia + 🇳🇪 flag: Niger + 🇳🇫 flag: Norfolk Island + 🇳🇬 flag: Nigeria + 🇳🇮 flag: Nicaragua + 🇳🇱 flag: Netherlands + 🇳🇴 flag: Norway + 🇳🇵 flag: Nepal + 🇳🇷 flag: Nauru + 🇳🇺 flag: Niue + 🇳🇿 flag: New Zealand + 🇴🇲 flag: Oman + 🇵🇦 flag: Panama + 🇵🇪 flag: Peru + 🇵🇫 flag: French Polynesia + 🇵🇬 flag: Papua New Guinea + 🇵🇭 flag: Philippines + 🇵🇰 flag: Pakistan + 🇵🇱 flag: Poland + 🇵🇲 flag: St. Pierre & Miquelon + 🇵🇳 flag: Pitcairn Islands + 🇵🇷 flag: Puerto Rico + 🇵🇸 flag: Palestinian Territories + 🇵🇹 flag: Portugal + 🇵🇼 flag: Palau + 🇵🇾 flag: Paraguay + 🇶🇦 flag: Qatar + 🇷🇪 flag: Réunion + 🇷🇴 flag: Romania + 🇷🇸 flag: Serbia + 🇷🇺 flag: Russia + 🇷🇼 flag: Rwanda + 🇸🇦 flag: Saudi Arabia + 🇸🇧 flag: Solomon Islands + 🇸🇨 flag: Seychelles + 🇸🇩 flag: Sudan + 🇸🇪 flag: Sweden + 🇸🇬 flag: Singapore + 🇸🇭 flag: St. Helena + 🇸🇮 flag: Slovenia + 🇸🇯 flag: Svalbard & Jan Mayen + 🇸🇰 flag: Slovakia + 🇸🇱 flag: Sierra Leone + 🇸🇲 flag: San Marino + 🇸🇳 flag: Senegal + 🇸🇴 flag: Somalia + 🇸🇷 flag: Suriname + 🇸🇸 flag: South Sudan + 🇸🇹 flag: São Tomé & Príncipe + 🇸🇻 flag: El Salvador + 🇸🇽 flag: Sint Maarten + 🇸🇾 flag: Syria + 🇸🇿 flag: Eswatini + 🇹🇦 flag: Tristan da Cunha + 🇹🇨 flag: Turks & Caicos Islands + 🇹🇩 flag: Chad + 🇹🇫 flag: French Southern Territories + 🇹🇬 flag: Togo + 🇹🇭 flag: Thailand + 🇹🇯 flag: Tajikistan + 🇹🇰 flag: Tokelau + 🇹🇱 flag: Timor-Leste + 🇹🇲 flag: Turkmenistan + 🇹🇳 flag: Tunisia + 🇹🇴 flag: Tonga + 🇹🇷 flag: Turkey + 🇹🇹 flag: Trinidad & Tobago + 🇹🇻 flag: Tuvalu + 🇹🇼 flag: Taiwan + 🇹🇿 flag: Tanzania + 🇺🇦 flag: Ukraine + 🇺🇬 flag: Uganda + 🇺🇲 flag: U.S. Outlying Islands + 🇺🇳 flag: United Nations + 🇺🇸 flag: United States + 🇺🇾 flag: Uruguay + 🇺🇿 flag: Uzbekistan + 🇻🇦 flag: Vatican City + 🇻🇨 flag: St. Vincent & Grenadines + 🇻🇪 flag: Venezuela + 🇻🇬 flag: British Virgin Islands + 🇻🇮 flag: U.S. Virgin Islands + 🇻🇳 flag: Vietnam + 🇻🇺 flag: Vanuatu + 🇼🇫 flag: Wallis & Futuna + 🇼🇸 flag: Samoa + 🇽🇰 flag: Kosovo + 🇾🇪 flag: Yemen + 🇾🇹 flag: Mayotte + 🇿🇦 flag: South Africa + 🇿🇲 flag: Zambia + 🇿🇼 flag: Zimbabwe + 🏴󠁧󠁢󠁥󠁮󠁧󠁿 flag: England + 🏴󠁧󠁢󠁳󠁣󠁴󠁿 flag: Scotland + 🏴󠁧󠁢󠁷󠁬󠁳󠁿 flag: Wales + ''; +} diff --git a/users/modules/eza.nix b/users/modules/eza.nix new file mode 100644 index 0000000..fab98e9 --- /dev/null +++ b/users/modules/eza.nix @@ -0,0 +1,8 @@ +{ + programs.eza = { + enable = true; + colors = "auto"; + icons = "auto"; + git = true; + }; +} diff --git a/users/modules/hyprland.nix b/users/modules/hyprland.nix new file mode 100644 index 0000000..de9bbc1 --- /dev/null +++ b/users/modules/hyprland.nix @@ -0,0 +1,8 @@ +{ + imports = [../../programs/hyprland.nix]; + modules.hyprland = { + enable = true; + config = builtins.readFile ./config/hypr/hyprland.conf; + waybar.style = ./config/waybar/style.css; + }; +} diff --git a/users/modules/kdeconnect.nix b/users/modules/kdeconnect.nix new file mode 100644 index 0000000..544c162 --- /dev/null +++ b/users/modules/kdeconnect.nix @@ -0,0 +1,6 @@ +{ + services.kdeconnect = { + enable = true; + indicator = true; + }; +} diff --git a/users/modules/kitty.nix b/users/modules/kitty.nix new file mode 100644 index 0000000..da291ad --- /dev/null +++ b/users/modules/kitty.nix @@ -0,0 +1,89 @@ +{ + programs.kitty = { + enable = true; + settings = { + enable_audio_bell = true; + enabled_layouts = "fat,fat:mirrored=true,tall,tall:mirrored=true"; + kitty_mod = "ctrl+shift"; + }; + keybindings = { + "alt+c" = "copy_to_clipboard"; + "kitty_mod+c" = "copy_to_clipboard"; + "alt+v" = "paste_from_clipboard"; + "kitty_mod+v" = "paste_from_clipboard"; + + "kitty_mod+s>c" = "show_scrollback"; + "kitty_mod+s>down" = "scroll_line_down"; + "kitty_mod+s>t" = "scroll_line_down"; + "kitty_mod+s>up" = "scroll_line_up"; + "kitty_mod+s>s" = "scroll_line_up"; + "kitty_mod+s>end" = "scroll_end"; + "kitty_mod+s>home" = "scroll_home"; + "kitty_mod+s>page_down" = "scroll_page_down"; + "kitty_mod+s>page_up" = "scroll_page_up"; + + "kitty_mod+enter" = "new_window"; + "kitty_mod+w>q" = "close_window"; + "kitty_mod+w>p" = "next_window"; + "kitty_mod+w>n" = "previous_window"; + "kitty_mod+w>f" = "move_window_forward"; + "kitty_mod+w>b" = "move_window_backward"; + "kitty_mod+w>t" = "move_window_to_top"; + "kitty_mod+w>r" = "start_resizing_window"; + "kitty_mod+w>1" = "first_window"; + "kitty_mod+w>2" = "second_window"; + "kitty_mod+w>3" = "third_window"; + "kitty_mod+w>4" = "fourth_window"; + "kitty_mod+w>5" = "fifth_window"; + "kitty_mod+w>6" = "sixth_window"; + "kitty_mod+w>7" = "seventh_window"; + "kitty_mod+w>8" = "eighth_window"; + "kitty_mod+w>9" = "ninth_window"; + "kitty_mod+w>0" = "tenth_window"; + + "kitty_mod+tab>n" = "next_tab"; + "kitty_mod+tab>p" = "previous_tab"; + "kitty_mod+tab>c" = "new_tab"; + "kitty_mod+tab>q" = "close_tab"; + "kitty_mod+tab>shift+n" = "move_tab_backward"; + "kitty_mod+tab>shift+p" = "move_tab_forward"; + "kitty_mod+tab>t" = "set_tab_title"; + + "kitty_mod+l" = "next_layout"; + + "kitty_mod+f>equal" = "change_font_size all 0"; + "kitty_mod+f>kp_add" = "change_font_size all +2.0"; + "kitty_mod+f>plus" = "change_font_size all +2.0"; + "kitty_mod+f>kp_subtract" = "change_font_size all -2.0"; + "kitty_mod+f>minus" = "change_font_size all -2.0"; + + "kitty_mod+shift+h" = "kitten hints"; + "kitty_mod+h>p" = "kitten hints --type path --program -"; + "kitty_mod+h>shift+p" = "kitten hints --type path"; + "kitty_mod+h>l" = "kitten hints --type line --program -"; + "kitty_mod+h>w" = "kitten hints --type word --program -"; + "kitty_mod+h>h" = "kitten hints --type hash --program -"; + "kitty_mod+h>n" = "kitten hints --type linenum"; + "kitty_mod+h>y" = "kitten hints --type hyperlink"; + + "kitty_mod+f10" = "toggle_maximized"; + "kitty_mod+f11" = "toggle_fullscreen"; + + "kitty_mod+a>equal" = "set_background_opacity 1"; + "kitty_mod+a>d" = "set_background_opacity default"; + "kitty_mod+a>plus" = "set_background_opacity +0.1"; + "kitty_mod+a>up" = "set_background_opacity +0.1"; + "kitty_mod+a>kp_add" = "set_background_opacity +0.1"; + "kitty_mod+a>minus" = "set_background_opacity -0.1"; + "kitty_mod+a>down" = "set_background_opacity -0.1"; + "kitty_mod+a>kp_substract" = "set_background_opacity -0.1"; + + "kitty_mod+delete" = "clear_terminal reset active"; + "kitty_mod+escape" = "kitty_shell window"; + "kitty_mod+f2" = "edit_config_file"; + "kitty_mod+n" = "new_os_window"; + "kitty_mod+o" = "pass_selection_to_program"; + "kitty_mod+u" = "kitten unicode_input"; + }; + }; +} diff --git a/users/modules/mbsync.nix b/users/modules/mbsync.nix new file mode 100644 index 0000000..bff8149 --- /dev/null +++ b/users/modules/mbsync.nix @@ -0,0 +1,60 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.mbsync; +in { + options.modules.mbsync = { + enable = mkEnableOption "Enables mbsync"; + passwordFile = mkOption { + type = types.str; + example = "/var/email/password"; + }; + service.enable = mkOption { + type = types.bool; + default = true; + }; + host = mkOption { + type = types.str; + default = "mail.phundrak.com"; + }; + user = mkOption { + type = types.str; + default = "lucien@phundrak.com"; + }; + }; + + config = mkIf cfg.enable { + systemd.user.services.mbsync.unitConfig.After = ["sops-nix.service"]; + services.mbsync.enable = cfg.service.enable; + programs.mbsync = { + enable = true; + extraConfig = '' + IMAPAccount Main + Host ${cfg.host} + User ${cfg.user} + PassCmd "cat ${cfg.passwordFile}" + SSLType IMAPS + SSLVersion TLSv1.2 + CertificateFile /etc/ssl/certs/ca-certificates.crt + + IMAPStore main-remote + Account Main + + MaildirStore main-local + Subfolders Verbatim + Path ~/Mail/ + Inbox ~/Mail/Inbox + + Channel main + Far :main-remote: + Near :main-local: + Create Both + SyncState * + Patterns * + ''; + }; + }; +} diff --git a/users/modules/mopidy.nix b/users/modules/mopidy.nix new file mode 100644 index 0000000..187e16b --- /dev/null +++ b/users/modules/mopidy.nix @@ -0,0 +1,46 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.modules.mopidy; +in { + options.modules.mopidy = { + enable = mkEnableOption "Enables Mopidy."; + }; + + config.services.mopidy = mkIf cfg.enable { + inherit (cfg) enable; + extensionPackages = with pkgs; [ + mopidy-bandcamp + mopidy-mpd + mopidy-mpris + mopidy-muse + mopidy-notify + mopidy-spotify + ]; + extraConfigFiles = [ + config.sops.secrets."mopidy/bandcamp".path + config.sops.secrets."mopidy/spotify".path + ]; + settings = { + mpd = { + enabled = true; + hostname = "::"; + port = 6600; + }; + mpris.enabled = true; + muse = { + enabled = true; + mopidy_host = "localhost"; + mopidy_port = 6690; + mopidy_ssl = false; + snapcast_host = "localhost"; + snapcast_port = 1780; + snapcast_ssl = false; + }; + }; + }; +} diff --git a/users/modules/mpd.nix b/users/modules/mpd.nix new file mode 100644 index 0000000..eb44017 --- /dev/null +++ b/users/modules/mpd.nix @@ -0,0 +1,21 @@ +{ + services.mpd = { + enable = true; + musicDirectory = "/home/phundrak/Music"; + playlistDirectory = "/home/phundrak/Music/playlists"; + extraConfig = '' + follow_outside_symlinks "yes" + follow_inside_symlinks "yes" + + bind_to_address "localhost" + auto_update "yes" + + audio_output { + type "fifo" + name "my_fifo" + path "/tmp/mpd.fifo" + format "44100:16:2" + } + ''; + }; +} diff --git a/users/modules/mpv.nix b/users/modules/mpv.nix new file mode 100644 index 0000000..50dbf4e --- /dev/null +++ b/users/modules/mpv.nix @@ -0,0 +1,60 @@ +{pkgs, ...}: { + programs.mpv = { + enable = true; + config = { + force-window = "immediate"; + ytdl-format = "bestvideo[height<=1080]+bestaudio"; + force-seekable = true; # force streams to be seekable + cache-default = 4000000; + slang = "jpn,jp,eng,en,fra,fr"; + alang = "eng,en,fra,fr"; + gpu-api = "vulkan"; + osc = true; + profile = "gpu-hq"; + geometry = "50%x50%"; + autofit-larger = "90%x90%"; + + # Screenshots + screenshot-format = "png"; + screenshot-high-bit-depth = true; + screenshot-png-compression = 6; + screenshot-directory = "~/Pictures/Screenshots/mpv"; + + deband = true; + deband-iterations = 2; + deband-threshold = 35; + deband-range = 20; + deband-grand = 5; + + dither-depth = "auto"; + + sub-auto = "fuzzy"; + + scale = "ewa_lanczossharp"; + dscale = "mitchel"; + cscale = "ewa_lanczossharp"; + }; + scripts = with pkgs.mpvScripts; [ + crop + encode + inhibit-gnome + mpris + mpv-cheatsheet + quality-menu + sponsorblock + thumbfast + # twitch-chat + youtube-chat + youtube-upnext + ]; + bindings = { + Q = "quit-watch-later"; + P = "show-progress"; + "/" = "add volume -2"; + "*" = "add volume 2"; + m = "cycle mute"; + M = "vf toggle hflip"; + "Ctrl+r" = "cycle_values video-rotate \"90\" \"180\" \"270\" \"0\""; + }; + }; +} diff --git a/users/modules/nh.nix b/users/modules/nh.nix new file mode 100644 index 0000000..e67d699 --- /dev/null +++ b/users/modules/nh.nix @@ -0,0 +1,20 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.nh; +in { + options.modules.nh.flake = mkOption { + type = types.path; + default = "/home/phundrak/.dotfiles"; + example = "/etc/nixos"; + }; + config.programs.nh = { + enable = true; + clean.enable = true; + clean.extraArgs = "--keep-since 15d --keep 5"; + inherit (cfg) flake; + }; +} diff --git a/users/modules/qt.nix b/users/modules/qt.nix new file mode 100644 index 0000000..d8ac7b7 --- /dev/null +++ b/users/modules/qt.nix @@ -0,0 +1,3 @@ +{ + qt.enable = true; +} diff --git a/users/modules/shell/bash.nix b/users/modules/shell/bash.nix new file mode 100644 index 0000000..bdc8a59 --- /dev/null +++ b/users/modules/shell/bash.nix @@ -0,0 +1,43 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.bash; +in { + options.modules.bash = { + enable = lib.mkEnableOption "enables bash"; + aliases = lib.mkOption { + type = types.attrsOf types.str; + default = {}; + example = { + cp = "cp -i"; + lns = "ln -si"; + }; + }; + bashrcExtra = lib.mkOption { + type = types.lines; + default = ""; + }; + }; + + config = lib.mkIf cfg.enable { + programs.bash = { + enable = true; + shellAliases = cfg.aliases; + shellOptions = [ + "histappend" + "cmdhist" + "lithist" + "checkwinsize" + "extglob" + "globstar" + "checkjobs" + "autocd" + "cdspell" + "dirspell" + ]; + }; + }; +} diff --git a/users/modules/shell/default.nix b/users/modules/shell/default.nix new file mode 100644 index 0000000..b4007dd --- /dev/null +++ b/users/modules/shell/default.nix @@ -0,0 +1,124 @@ +{ + config, + lib, + ... +}: +with lib; let + aliases = { + df = "df -H"; + diskspace = "sudo df -h | grep -E \"sd|lv|Size\""; + du = "du -ch"; + meminfo = "free -m -l -t"; + gpumeminfo = "grep -i --color memory /var/log/Xorg.0.log"; + cpuinfo = "lscpu"; + pscpu = "ps auxf | sort -nr -k 3"; + pscpu10 = "ps auxf | sort -nr -k 3 | head -10"; + psmem = "ps auxf | sort -nr -k 4"; + psmem10 = "ps auxf | sort -nr -k 4 | head -10"; + + s = "systemctl"; + + dc = "docker compose"; + dcd = "docker compose down"; + dcl = "docker compose logs"; + dclf = "docker compose logs -f"; + dcp = "docker compose pull"; + dcu = "docker compose up"; + dcud = "docker compose up -d"; + dcudp = "docker compose up -d --pull=always"; + dcr = "docker compose restart"; + enw = "emacsclient -nw"; + e = "emacsclient -n -c"; + + cp = "cp -i"; + rsync = "rsync -Pa --progress"; + ln = "ln -i"; + lns = "ln -si"; + mv = "mv -i"; + rm = "rm -Iv"; + rmd = "rm --preserve-root -Irv"; + rmdf = "rm --preserve-root -Irfv"; + rmf = "rm --preserve-root -Ifv"; + chgrp = "chgrp --preserve-root -v"; + chmod = "chmod --preserve-root -v"; + chown = "chown --preserve-root -v"; + lsl = "eza -halg@ --group-directories-first --git"; + + flac = "yt-dlp -x --audio-format flac --audio-quality 0 o \"~/Music/%(uploader)s/%(title)s.%(ext)s\""; + please = "sudo -A"; + wget = "wget --hsts-file=\"$XDG_DATA_HOME/wget-hsts\" -c"; + }; + cfg = config.modules.shell; +in { + imports = [ + ./bash.nix + ./fish.nix + ./starship.nix + ./zsh.nix + ]; + + options.modules.shell = { + enableBash = mkOption { + type = types.bool; + default = true; + description = "enables bash"; + }; + enableFish = mkOption { + type = types.bool; + default = true; + description = "enables fish"; + }; + enableZsh = mkOption { + type = types.bool; + default = true; + description = "enables zsh"; + }; + starship = { + enable = mkEnableOption "Enables the starship prompt."; + jjIntegration = mkEnableOption "Enables Jujutsu integration in starship."; + }; + zoxide = { + enable = mkOption { + type = types.bool; + default = true; + description = "enables zoxide"; + }; + replaceCd = mkOption { + type = types.bool; + default = true; + description = "makes zoxide replace cd"; + }; + }; + }; + + config = { + home.shell = { + enableFishIntegration = mkDefault cfg.enableFish; + enableBashIntegration = mkDefault cfg.enableBash; + enableZshIntegration = mkDefault cfg.enableZsh; + }; + + modules = { + fish = { + enable = mkDefault cfg.enableFish; + abbrs = mkDefault aliases; + }; + bash = { + enable = mkDefault cfg.enableBash; + aliases = mkDefault aliases; + }; + zsh = { + enable = mkDefault cfg.enableZsh; + abbrs = mkDefault aliases; + }; + inherit (cfg) starship; + }; + + programs.zoxide = mkIf cfg.zoxide.enable { + enable = true; + options = mkIf cfg.zoxide.replaceCd [ + "--cmd cd" + ]; + }; + }; +} diff --git a/users/modules/shell/fish.nix b/users/modules/shell/fish.nix new file mode 100644 index 0000000..84854a4 --- /dev/null +++ b/users/modules/shell/fish.nix @@ -0,0 +1,75 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.modules.fish; +in { + options.modules.fish = { + enable = lib.mkEnableOption "enables fish"; + abbrs = lib.mkOption { + type = types.attrsOf types.str; + default = {}; + example = { + cp = "cp -i"; + lns = "ln -si"; + }; + }; + }; + + config = lib.mkIf cfg.enable { + programs.fish = { + enable = true; + shellAbbrs = cfg.abbrs; + preferAbbrs = true; + shellInit = '' + function fish_command_not_found + __fish_default_command_not_found_handler $argv + end + ''; + plugins = [ + { + name = "bass"; + inherit (pkgs.fishPlugins.bass) src; + # src = pkgs.fishPlugins.bass.src; + } + { + name = "colored-man-pages"; + inherit (pkgs.fishPlugins.colored-man-pages) src; + } + { + name = "done"; + inherit (pkgs.fishPlugins.done) src; + } + { + name = "fzf"; + inherit (pkgs.fishPlugins.fzf) src; + } + { + name = "pisces"; + inherit (pkgs.fishPlugins.pisces) src; + } + { + name = "getopts.fish"; + src = pkgs.fetchFromGitHub { + owner = "jorgebucaran"; + repo = "getopts.fish"; + rev = "4b74206725c3e11d739675dc2bb84c77d893e901"; + sha256 = "9hRFBmjrCgIUNHuOJZvOufyLsfreJfkeS6XDcCPesvw="; + }; + } + { + name = "replay.fish"; + src = pkgs.fetchFromGitHub { + owner = "jorgebucaran"; + repo = "replay.fish"; + rev = "d2ecacd3fe7126e822ce8918389f3ad93b14c86c"; + sha256 = "TzQ97h9tBRUg+A7DSKeTBWLQuThicbu19DHMwkmUXdg="; + }; + } + ]; + }; + }; +} diff --git a/users/modules/shell/starship.nix b/users/modules/shell/starship.nix new file mode 100644 index 0000000..9a3ccb3 --- /dev/null +++ b/users/modules/shell/starship.nix @@ -0,0 +1,45 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.starship; +in { + options.modules.starship = { + enable = mkEnableOption "Enables the starship prompt."; + jjIntegration = mkEnableOption "Enables Jujutsu integration in starship."; + }; + + config.programs.starship = mkIf cfg.enable { + inherit (cfg) enable; + enableTransience = true; + settings.custom = { + jj = { + description = "The current jj status"; + detect_folders = [".jj"]; + symbol = "🥋 "; + command = '' + jj log --revisions @ --no-graph --ignore-working-copy --color always --limit 1 --template ' + separate(" ", + change_id.shortest(4), + bookmarks, + "|", + concat( + if(conflict, "💥"), + if(divergent, "🚧"), + if(hidden, "👻"), + if(immutable, "🔒"), + ), + raw_escape_sequence("\x1b[1;32m") ++ if(empty, "(empty)"), + raw_escape_sequence("\x1b[1;32m") ++ coalesce( + truncate_end(29, description.first_line(), "…"), + "(no description set)", + ) ++ raw_escape_sequence("\x1b[0m"), + ) + ' + ''; + }; + }; + }; +} diff --git a/users/modules/shell/zsh.nix b/users/modules/shell/zsh.nix new file mode 100644 index 0000000..090df13 --- /dev/null +++ b/users/modules/shell/zsh.nix @@ -0,0 +1,96 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.modules.zsh; +in { + options.modules.zsh = { + enable = lib.mkEnableOption "enables zsh"; + abbrs = lib.mkOption { + type = types.attrsOf types.str; + default = {}; + example = { + cp = "cp -i"; + lns = "ln -si"; + }; + }; + zshrcExtra = lib.mkOption { + type = types.lines; + default = '' + bindkey -e + bindkey '^p' history-search-backward + bindkey '^n' history-search-forward + + # Completion styling + zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' + zstyle ':completion:*' list-colors "''${(s.:.)LS_COLORS}" + zstyle ':completion:*' menu no + zstyle ':fzf-tab:complete:cd:*' fzf-preview '${pkgs.eza}/bin/eza $realpath' + ''; + }; + }; + + config.programs.zsh = lib.mkIf cfg.enable { + enable = true; + autocd = true; + autosuggestion = { + enable = true; + strategy = ["match_prev_cmd" "completion"]; + }; + enableCompletion = true; + history = { + findNoDups = true; + ignoreAllDups = true; + ignoreDups = true; + ignoreSpace = true; + path = "${config.xdg.dataHome}/zsh/zsh_history"; + saveNoDups = true; + }; + historySubstringSearch.enable = true; + initContent = cfg.zshrcExtra; + oh-my-zsh = { + enable = true; + plugins = [ + "dirhistory" + "sudo" + ]; + }; + plugins = [ + { + name = "fzf-tab"; + src = pkgs.fetchFromGitHub { + owner = "Aloxaf"; + repo = "fzf-tab"; + rev = "v1.2.0"; + sha256 = "sha256-q26XVS/LcyZPRqDNwKKA9exgBByE0muyuNb0Bbar2lY="; + }; + } + { + name = "auto-notify"; + src = pkgs.fetchFromGitHub { + owner = "MichaelAquilina"; + repo = "zsh-auto-notify"; + rev = "0.11.0"; + sha256 = "sha256-8r5RsyldJIzlWr9+G8lrkHvJ8KxTVO859M//wDnYOUY="; + }; + } + { + name = "zsh-autopair"; + src = pkgs.fetchFromGitHub { + owner = "hlissner"; + repo = "zsh-autopair"; + rev = "449a7c3d095bc8f3d78cf37b9549f8bb4c383f3d"; + sha256 = "sha256-3zvOgIi+q7+sTXrT+r/4v98qjeiEL4Wh64rxBYnwJvQ="; + }; + } + ]; + syntaxHighlighting.enable = true; + zsh-abbr = { + enable = true; + abbreviations = cfg.abbrs; + }; + }; +} diff --git a/users/modules/ssh.nix b/users/modules/ssh.nix new file mode 100644 index 0000000..59ce48f --- /dev/null +++ b/users/modules/ssh.nix @@ -0,0 +1,23 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.modules.ssh; +in { + options.modules.ssh = { + enable = mkEnableOption "enables SSH"; + hosts = mkOption { + type = types.nullOr types.path; + default = null; + }; + }; + + config = { + programs.ssh = mkIf cfg.enable { + enable = true; + includes = mkIf (cfg.hosts != null) [cfg.hosts]; + }; + }; +} diff --git a/users/modules/tealdeer.nix b/users/modules/tealdeer.nix new file mode 100644 index 0000000..75cebfd --- /dev/null +++ b/users/modules/tealdeer.nix @@ -0,0 +1,6 @@ +{ + programs.tealdeer = { + enable = true; + enableAutoUpdates = true; + }; +} diff --git a/users/modules/tmux.nix b/users/modules/tmux.nix new file mode 100644 index 0000000..acc2262 --- /dev/null +++ b/users/modules/tmux.nix @@ -0,0 +1,86 @@ +{pkgs, ...}: { + programs.tmux = { + enable = true; + baseIndex = 1; + clock24 = true; + customPaneNavigationAndResize = true; + keyMode = "vi"; + mouse = true; + newSession = true; + prefix = "M-space"; + plugins = with pkgs.tmuxPlugins; [ + cpu + nord + prefix-highlight + resurrect + sensible + yank + ]; + extraConfig = '' + set-option -sa terminal-overrides ",xterm*:Tc" + + unbind C-b + + bind-key -T prefix « select-window -p + bind-key -T prefix » select-window -n + bind-key -T prefix Tab switch-client -T windows + bind-key -T prefix w switch-client -T pane + bind-key -T prefix y switch-client -T copy-mode + + bind-key -T pane / split-window -h -c "#{pane-current_path}" + bind-key -T pane - split-window -v -c "#{pane-current_path}" + bind-key -T pane c select-pane -L + bind-key -T pane t select-pane -D + bind-key -T pane s select-pane -U + bind-key -T pane r select-pane -R + bind-key -T pane f resize-pane -Z + bind-key -T pane . switch-client -T pane-resize + + bind-key -T pane-resize c resize-pane -L 5\; switch-client -T pane-resize + bind-key -T pane-resize t resize-pane -D 5\; switch-client -T pane-resize + bind-key -T pane-resize s resize-pane -U 5\; switch-client -T pane-resize + bind-key -T pane-resize r resize-pane -R 5\; switch-client -T pane-resize + bind-key -T pane-resize C resize-pane -L\; switch-client -T pane-resize + bind-key -T pane-resize T resize-pane -D\; switch-client -T pane-resize + bind-key -T pane-resize S resize-pane -U\; switch-client -T pane-resize + bind-key -T pane-resize R resize-pane -R\; switch-client -T pane-resize + + bind-key -T windows c new-window + bind-key -T windows n next-window + bind-key -T windows p previous-window + + bind-key -T windows \" select-window -t :=1 + bind-key -T windows « select-window -t :=2 + bind-key -T windows » select-window -t :=3 + bind-key -T windows ( select-window -t :=4 + bind-key -T windows ) select-window -t :=5 + bind-key -T windows @ select-window -t :=6 + bind-key -T windows + select-window -t :=7 + bind-key -T windows - select-window -t :=8 + bind-key -T windows / select-window -t :=9 + bind-key -T windows * select-window -t :=10 + + unbind -T copy-mode-vi H + unbind -T copy-mode-vi J + unbind -T copy-mode-vi K + unbind -T copy-mode-vi L + unbind -T copy-mode-vi h + unbind -T copy-mode-vi j + unbind -T copy-mode-vi k + unbind -T copy-mode-vi l + + bind-key -T copy-mode-vi v send-keys -X begin-selection + bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle + bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel + bind-key -T copy-mode-vi C send-keys -X top-line + bind-key -T copy-mode-vi J send-keys -X jump-to-backward + bind-key -T copy-mode-vi S send-keys -X scroll-up + bind-key -T copy-mode-vi R send-keys -X bottom-line + bind-key -T copy-mode-vi T send-keys -X scroll-down + bind-key -T copy-mode-vi c send-keys -X cursor-left + bind-key -T copy-mode-vi t send-keys -X cursor-down + bind-key -T copy-mode-vi s send-keys -X cursor-up + bind-key -T copy-mode-vi r send-keys -X cursor-right + ''; + }; +} diff --git a/users/modules/vcs/default.nix b/users/modules/vcs/default.nix new file mode 100644 index 0000000..571b187 --- /dev/null +++ b/users/modules/vcs/default.nix @@ -0,0 +1,112 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.modules.vcs; +in { + imports = [./git.nix ./jujutsu.nix]; + + options.modules.vcs = { + git = { + enable = mkEnableOption "enables git"; + sendmail = { + enable = mkOption { + type = types.bool; + default = true; + }; + server = mkOption { + type = types.nullOr types.str; + default = "mail.phundrak.com"; + }; + user = mkOption { + type = types.nullOr types.str; + default = null; + }; + encryption = mkOption { + type = types.enum ["tls" "ssl" "none"]; + default = "none"; + }; + port = mkOption { + type = types.nullOr types.int; + default = 587; + }; + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to a file containing the password necessary for authenticating + against the mailserver. + + This file should contain the password only, with no newline. + ''; + }; + }; + browser = mkOption { + type = types.nullOr types.str; + example = "${pkgs.firefox}/bin/firefox"; + default = null; + }; + completeConfig = mkEnableOption "Complete configuration for workstations"; + mergeTool = mkOption { + type = types.str; + default = "ediff"; + }; + emacs = { + integration = mkEnableOption "enables Emacs integration"; + pkg = mkOption { + type = types.package; + default = pkgs.emacs; + }; + }; + }; + jj.enable = mkEnableOption "enables jujutsu"; + name = mkOption { + type = types.str; + default = "Lucien Cartier-Tilet"; + }; + email = mkOption { + type = types.str; + default = "lucien@phundrak.com"; + }; + editor = mkOption { + type = types.str; + default = "${pkgs.emacs}/bin/emacsclient -c -a ${pkgs.emacs}/bin/emacs"; + }; + publicKey = { + content = mkOption { + type = types.nullOr types.str; + example = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGj+J6N6SO+4P8dOZqfR1oiay2yxhhHnagH52avUqw5h"; + default = null; + }; + file = mkOption { + type = with types; nullOr path; + default = "/home/phundrak/.ssh/id_ed25519.pub"; + }; + }; + }; + + config = lib.mkIf (cfg.git.enable || cfg.jj.enable) { + home.file.".ssh/allowed_signers".text = mkIf (cfg.publicKey.content != null) (mkDefault '' + ${cfg.email} namespaces="git" ${cfg.publicKey.content} + ''); + modules = { + git = mkIf cfg.git.enable { + inherit (cfg.git) enable sendmail browser completeConfig emacs mergeTool; + inherit (cfg) email name editor; + publicKeyFile = cfg.publicKey.file; + }; + jj = mkIf cfg.jj.enable { + inherit (cfg.jj) enable; + inherit (cfg) name email editor; + signing.enable = cfg.publicKey.content != null; + signing.sshKey = + if (cfg.publicKey.file == null) + then cfg.publicKey.content + else cfg.publicKey.file; + }; + }; + }; +} diff --git a/users/modules/vcs/git.nix b/users/modules/vcs/git.nix new file mode 100644 index 0000000..e877f9c --- /dev/null +++ b/users/modules/vcs/git.nix @@ -0,0 +1,273 @@ +{ + lib, + config, + pkgs, + ... +}: +with lib; let + cfg = config.modules.git; +in { + options.modules.git = { + enable = mkEnableOption "enables git"; + email = mkOption { + type = types.str; + default = "lucien@phundrak.com"; + }; + name = mkOption { + type = types.str; + default = "Lucien Cartier-Tilet"; + }; + sendmail = { + enable = mkOption { + type = types.bool; + default = true; + }; + server = mkOption { + type = types.nullOr types.str; + default = "mail.phundrak.com"; + }; + user = mkOption { + type = types.nullOr types.str; + default = null; + }; + encryption = mkOption { + type = types.enum ["tls" "ssl" "none"]; + default = "none"; + }; + port = mkOption { + type = types.nullOr types.int; + default = 587; + }; + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to a file containing the password necessary for authenticating + against the mailserver. + + This file should contain the password only, with no newline. + ''; + }; + }; + browser = mkOption { + type = types.nullOr types.str; + example = "${pkgs.firefox}/bin/firefox"; + default = null; + }; + completeConfig = mkEnableOption "Complete configuration for workstations"; + emacs = { + integration = mkEnableOption "enables Emacs integration"; + pkg = mkOption { + type = types.package; + default = pkgs.emacs; + }; + }; + mergeTool = mkOption { + type = types.str; + default = "ediff"; + }; + editor = mkOption { + type = types.str; + default = "${pkgs.emacs}/bin/emacsclient -c -a ${pkgs.emacs}/bin/emacs"; + }; + publicKeyFile = mkOption { + type = types.nullOr types.str; + default = null; + }; + }; + + config = lib.mkIf cfg.enable { + programs.git = let + smtpEmail = + if (cfg.sendmail.user == null) + then cfg.email + else cfg.sendmail.user; + in { + enable = true; + userEmail = cfg.email; + userName = cfg.name; + extraConfig = { + color.ui = "auto"; + column.ui = "auto"; + tag.sort = "version:refname"; + core = mkIf cfg.completeConfig { + compression = 9; + inherit (cfg) editor; + whitespace = "fix,-indent-with-non-tab,trailing-space"; + preloadindex = true; + }; + status = { + branch = true; + showStash = true; + }; + diff = { + algorithm = "histogram"; + colorMoved = "plain"; + mnemonicPrefix = true; + renames = "copy"; + interHunkContext = 10; + }; + commit.gpgsign = cfg.publicKeyFile != null; + gpg.format = "ssh"; + gpg.ssh.allowedSignersFile = (mkIf (cfg.publicKeyFile != null)) "~/.ssh/allowed_signers"; + init.defaultBranch = "main"; + pull.rebase = true; + push = { + default = "simple"; + autoSetupRemote = true; + followTags = true; + }; + rebase = { + autoSquash = true; + autoStash = true; + missingCommitsCheck = "warn"; + updateRefs = true; + }; + help.autocorrect = "prompt"; + user.signingkey = mkIf (cfg.publicKeyFile != null) cfg.publicKeyFile; + web.browser = mkIf (cfg.browser != null) cfg.browser; + sendemail = mkIf cfg.sendmail.enable { + smtpserver = cfg.sendmail.server; + smtpuser = smtpEmail; + smtpencryption = cfg.sendmail.encryption; + smtpserverport = cfg.sendmail.port; + }; + credentials = mkIf (cfg.sendmail.passwordFile != null) { + "smtp://${smtpEmail}@${cfg.sendmail.server}:${toString cfg.sendmail.port}" = { + helper = "cat ${cfg.sendmail.passwordFile}"; + }; + }; + magithub = mkIf cfg.emacs.integration { + online = true; + "status" = { + includeStatusHeader = true; + includePullRequestsSection = true; + includeIssuesSection = true; + }; + }; + merge = { + tool = mkIf cfg.completeConfig cfg.mergeTool; + conflictstyle = "zdiff3"; + }; + mergetool.ediff.cmd = mkIf (cfg.emacs.integration && cfg.completeConfig) "\"${cfg.emacs.pkg} --eval \" (progn (defun ediff-write-merge-buffer () (let ((file ediff-merge-store-file)) (set-buffer ediff-buffer-C) (write-region (point-min) (point-max) file) (message \\\"Merge buffer saved in: %s\\\" file) (set-buffer-modified-p nil) (sit-for 1))) (setq ediff-quit-hook 'kill-emacs ediff-quit-merge-hook 'ediff-write-merge-buffer) (ediff-merge-files-with-ancestor \\\"$LOCAL\\\" \\\"$REMOTE\\\" \\\"$BASE\\\" nil \\\"$MERGED\\\"))\"\""; + github.user = "phundrak"; + url = { + "https://phundrak@github.com" = { + insteadOf = "https://github.com"; + }; + "https://phundrak@labs.phundrak.com" = { + insteadOf = "https://labs.phundrak.com"; + }; + "https://github.com/RustSec/advisory-db" = { + insteadOf = "https://github.com/RustSec/advisory-db"; + }; + "git@github.com:Phundrak/" = { + insteadOf = "pg:"; + }; + "git@labs.phundrak.com/phundrak:" = { + insteadOf = "p:"; + }; + "git@github.com" = { + insteadOf = "gh:"; + }; + "git@labs.phundrak.com" = { + insteadOf = "labs:"; + }; + }; + }; + ignores = [ + ".env" + ".direnv/" + + "*~" + "\#*\#" + "*.elc" + "auto-save-list" + ".\#*" + "*_flymake.*" + "/auto/" + ".projectile" + ".dir-locals.el" + + "# Org mode files" + ".org-id-locations" + "*_archive" + + "*.out" + "*.o" + "*.so" + + "# Archives" + "*.7zz" + "*.dmg" + "*.gz" + "*.iso" + "*.jar" + "*.rar" + "*.tar" + "*.zip" + + "*.log" + "*.sqlite" + + "dist/" + ]; + aliases = { + a = "add --all"; + aca = "!git add --all && git commit --amend"; + acan = "!git add --all && git commit --amend --no-edit"; + ap = "add --patch"; + b = "branch"; + bd = "branch -d"; + bdd = "branch -D"; + c = "commit -S"; + ca = "commit -Sa"; + can = "commit -Sa --no-edit"; + cm = "commit -Sm"; + cam = "commit -Sam"; + co = "checkout"; + cob = "checkout -b"; + cod = "checkout develop"; + cl = "clone"; + cl1 = "clone --depth 1"; + f = "fetch"; + fp = "fetch --prune"; + ps = "push"; + psf = "push --force-with-lease"; + pso = "push origin"; + psfo = "push --force-with-lease origin"; + pushall = "!git remote \vert{} xargs -L1 git push"; + psl = "!git remote \vert{} xargs -L1 git push"; + pullall = "!git remote \vert{} xargs -L1 git pull"; + pll = "!git remote \vert{} xargs -L1 git pull"; + pl = "pull"; + pb = "pull --rebase"; + r = "rebase"; + ra = "rebase --abort"; + rc = "rebase --continue"; + rd = "rebase develop"; + ri = "rebase -i"; + rmf = "rm -f"; + rmd = "rm -r"; + rmdf = "rm -rf"; + sm = "submodule"; + sms = "submodule status"; + sma = "submodule add"; + smu = "submodule update"; + smui = "submodule update --init"; + smuir = "submodule update --init --recursive"; + st = "stash"; + stc = "stash clear"; + stp = "stash pop"; + stw = "stash show"; + u = "reset --"; + d = "diff -w"; + l = "log --all --oneline --graph --decorate --pretty=format':%C(magenta)%h %C(white) %an %ar%C(auto) %D%n%s%n'"; + s = "status"; + staged = "diff --cached"; + upstream = "!git push -u origin HEAD"; + unstage = "reset --"; + }; + }; + }; +} diff --git a/users/modules/vcs/jujutsu.nix b/users/modules/vcs/jujutsu.nix new file mode 100644 index 0000000..487ab0c --- /dev/null +++ b/users/modules/vcs/jujutsu.nix @@ -0,0 +1,55 @@ +{ + lib, + config, + pkgs, + ... +}: +with lib; let + cfg = config.modules.jj; +in { + options.modules.jj = { + enable = mkEnableOption "enables jj"; + name = mkOption { + type = types.str; + default = "Lucien Cartier-Tilet"; + }; + email = mkOption { + type = types.str; + default = "lucien@phundrak.com"; + }; + editor = mkOption { + type = types.str; + default = "${pkgs.emacs}/bin/emacsclient -c -a ${pkgs.emacs}/bin/emacs"; + }; + signing = { + enable = mkEnableOption "enables signing jj commits"; + sshKey = mkOption { + type = with types; nullOr (either path str); + example = "~/.ssh/id_ed25519.pub"; + default = "~/.ssh/id_ed25519.pub"; + description = "Path to the public SSH key or its content."; + }; + }; + }; + + config.programs.jujutsu = mkIf cfg.enable { + enable = true; + settings = { + user = { + inherit (cfg) name email; + }; + ui = { + default-command = "st"; + pager = ":builtin"; + inherit (cfg) editor; + }; + signing = mkIf cfg.signing.enable { + behavior = "own"; + backend = "ssh"; + key = cfg.signing.sshKey; + backends."ssh.allowed-signers" = "~/.ssh/allowed_signers"; + backends."ssh.program" = "${pkgs.openssh}/bin/ssh-keygen"; + }; + }; + }; +} diff --git a/users/modules/wofi.nix b/users/modules/wofi.nix new file mode 100644 index 0000000..d89dff6 --- /dev/null +++ b/users/modules/wofi.nix @@ -0,0 +1,68 @@ +{ + programs.wofi = { + enable = true; + settings = { + modi = "ssh,drun,combi"; + sidebar-mode = false; + width = 30; + line-margin = 10; + lines = 6; + columns = 2; + display-ssh = ""; + display-run = ""; + display-drun = ""; + display-window = ""; + display-combi = ""; + show-icons = true; + }; + # from https://github.com/alxndr13/wofi-nord-theme + style = '' + * { + font-family: "Hack", monospace; + } + + window { + background-color: #3B4252; + } + + #input { + margin: 5px; + border-radius: 0px; + border: none; + background-color: #3B4252; + color: white; + } + + #inner-box { + background-color: #383C4A; + } + + #outer-box { + margin: 2px; + padding: 10px; + background-color: #383C4A; + } + + #scroll { + margin: 5px; + } + + #text { + padding: 4px; + color: white; + } + + #entry:nth-child(even){ + background-color: #404552; + } + + #entry:selected { + background-color: #4C566A; + } + + #text:selected { + background: transparent; + } + ''; + }; +} diff --git a/users/modules/yt-dlp.nix b/users/modules/yt-dlp.nix new file mode 100644 index 0000000..9354546 --- /dev/null +++ b/users/modules/yt-dlp.nix @@ -0,0 +1,10 @@ +{ + programs.yt-dlp = { + enable = true; + settings = { + embed-thumbnail = true; + embed-subs = true; + sub-langs = "all"; + }; + }; +} diff --git a/users/phundrak/config/hypr/hyprland.conf b/users/phundrak/config/hypr/hyprland.conf new file mode 100644 index 0000000..d7450b6 --- /dev/null +++ b/users/phundrak/config/hypr/hyprland.conf @@ -0,0 +1,249 @@ +env = XCURSOR_SIZE,24 +env = SDL_VIDEODRIVER,wayland + +input { + kb_layout = fr + kb_variant = bepo_afnor + kb_model = + kb_options = caps:ctrl_modifier + kb_rules = + numlock_by_default = true + + follow_mouse = 1 + + touchpad { + natural_scroll = false + } + + sensitivity = 0 # -1.0 - 1.0, 0 means no modification. +} + +monitor = HDMI-A-1, 2560x1080, 0x0, 1 +monitor = eDP-1, 1920x1080@120, 2560x0, 1 + +general { + gaps_in = 5 + gaps_out = 20 + border_size = 2 + col.active_border = rgb(81a1c1) rgb(a3be8c) 45deg + col.inactive_border = rgb(4c566a) + layout = dwindle +} + +decoration { + rounding = 5 + blur { + enabled = true + size = 9 + passes = 1 + } + shadow { + enabled = true + color = rgba(2e3440aa) + range = 4 + render_power = 3 + } +} + +animations { + enabled = true + bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + animation = windows, 1, 7, myBezier + animation = windowsOut, 1, 7, default, popin 80% + animation = border, 1, 10, default + animation = borderangle, 1, 8, default + animation = fade, 1, 7, default + animation = workspaces, 1, 6, default +} + +dwindle { + pseudotile = true + preserve_split = true +} + +exec-once = wpaperd +exec-once = waybar + +exec-once = pactl load-module module-switch-on-connect +exec-once = mpc stop + +exec-once = xfce-polkit + +exec-once = swaync + +exec-once = wlsunset -l 48.5 -L 2.2 -d 1500 + +exec-once = nm-applet +exec-once = blueman-applet + +$left = c +$right = r +$up = s +$down = t +$menu = rofi -combi-modi drun -show combi + +bind = SUPER, Return, exec, kitty +bind = SUPER, Space, submap, leader +bind = , Print, submap, screenshot + +submap = leader +bind = , l, exec, plock +bind = , l, submap, reset +bind = , a, submap, apps +bind = , b, submap, buffers +bind = , w, submap, windows +bind = , escape, submap, reset +bind = CTRL, g, submap, reset + +submap = apps +bind = , b, exec, zen-browser +bind = , b, submap, reset +bind = SHIFT, b, exec, qutebrowser +bind = SHIFT, b, submap, reset +bind = , d, exec, vesktop +bind = , d, submap, reset +bind = , e, exec, emacsclient -c -n +bind = , e, submap, reset +bind = , g, exec, gimp +bind = , g, submap, reset +bind = , n, exec, nemo +bind = , n, submap, reset +bind = , r, submap, rofi +bind = , u, exec, $menu +bind = , u, submap, reset +bind = , escape, submap, reset +bind = CTRL, g, submap, reset +submap = buffers +bind = , d, killactive, +bind = , d, submap, reset +bind = , escape, submap, reset +bind = CTRL, g, submap, reset +submap = resize +binde = , $left, resizeactive, -10 0 +binde = , $right, resizeactive, 10 0 +binde = , $up, resizeactive, 0 -10 +binde = , $down, resizeactive, 0 10 +bind = , q, submap, reset +bind = , escape, submap, reset +bind = CTRL, g, submap, reset +submap = rofi +bind = , a, exec, awiki +bind = , a, submap, reset +bind = , b, exec, bluetooth-connect +bind = , b, submap, reset +bind = , e, exec, rofi-emoji +bind = , e, submap, reset +bind = , r, exec, $menu +bind = , r, submap, reset +bind = , s, exec, rofi -show ssh +bind = , s, submap, reset +bind = , y, exec, ytplay +bind = , y, submap, reset +bind = SHIFT, y, exec, rofi-ytdl +bind = SHIFT, y, submap, reset +bind = , escape, submap, reset +bind = CTRL, g, submap, reset +submap = screenshot +bind = , Print, exec, screenshot +bind = , Print, submap, reset +bind = , d, exec, screenshot -d 3 +bind = , d, submap, reset +bind = Shift, d, exec, screenshot -sced 3 +bind = Shift, d, submap, reset +bind = , e, exec, screenshot -sec +bind = , e, submap, reset +bind = , s, exec, screenshot -s +bind = , s, submap, reset +bind = Shift, s, exec, screenshot -sc +bind = Shift, s, submap, reset +bind = , escape, submap, reset +bind = CTRL, g, submap, reset +submap = windows +bind = , period, submap, resize +bind = , $left, movefocus, l +bind = , $left, submap, reset +bind = , $right, movefocus, r +bind = , $right, submap, reset +bind = , $up, movefocus, u +bind = , $up, submap, reset +bind = , $down, movefocus, d +bind = , $down, submap, reset +bind = SHIFT, $left, movewindow, l +bind = SHIFT, $left, submap, reset +bind = SHIFT, $right, movewindow, r +bind = SHIFT, $right, submap, reset +bind = SHIFT, $up, movewindow, u +bind = SHIFT, $up, submap, reset +bind = SHIFT, $down, movewindow, d +bind = SHIFT, $down, submap, reset +bind = CTRL_SHIFT, $left, moveworkspacetomonitor, e+0 +1 +bind = CTRL_SHIFT, $left, submap, reset +bind = CTRL_SHIFT, $right, moveworkspacetomonitor, e+0 -1 +bind = CTRL_SHIFT, $right, submap, reset +bind = , d, killactive, +bind = , d, submap, reset +bind = , f, fullscreen, +bind = , f, submap, reset +bind = SHIFT, f, togglefloating, +bind = SHIFT, f, submap, reset +bind = , escape, submap, reset +bind = CTRL, g, submap, reset + +submap = reset +bindl = , XF86AudioPlay, exec, playerctl play-pause +bindl = , XF86AudioPause, exec, playerctl pause +bindl = , XF86AudioStop, exec, playerctl stop +bindl = , XF86AudioPrev, exec, playerctl previous +bindl = , XF86AudioNext, exec, playerctl next +bindl = , XF86AudioForward, exec, playerctl position +1 +bindl = , XF86AudioRewind, exec, playerctl position -1 +bindl = , XF86AudioRaiseVolume, exec, pamixer -i 2 +bindl = , XF86AudioLowerVolume, exec, pamixer -d 2 +bindl = , XF86MonBrightnessUp, exec, xbacklight -perceived -inc 2 +bindl = , XF86MonBrightnessDown, exec, xbacklight -perceived -dec 2 +bindl = , XF86KbdBrightnessUp, exec, xbacklight -perceived -inc 2 +bindl = , XF86KbdBrightnessDown, exec, xbacklight -perceived -dec 2 +bind = SUPER, $left, movefocus, l +bind = SUPER, $right, movefocus, r +bind = SUPER, $up, movefocus, u +bind = SUPER, $down, movefocus, d +bind = SUPER_SHIFT, $left, movewindow, l +bind = SUPER_SHIFT, $left, submap, reset +bind = SUPER_SHIFT, $right, movewindow, r +bind = SUPER_SHIFT, $right, submap, reset +bind = SUPER_SHIFT, $up, movewindow, u +bind = SUPER_SHIFT, $up, submap, reset +bind = SUPER_SHIFT, $down, movewindow, d +bind = SUPER_SHIFT, $down, submap, reset +bind = SUPER_CTRL_SHIFT, $left, moveworkspacetomonitor, e+0 +1 +bind = SUPER_CTRL_SHIFT, $left, submap, reset +bind = SUPER_CTRL_SHIFT, $right, moveworkspacetomonitor, e+0 -1 +bind = SUPER_CTRL_SHIFT, $right, submap, reset +bind = SUPER, Tab, cyclenext, +bind = SUPER_SHIFT, Tab, cyclenext, prev +bindm = SUPER, mouse:272, movewindow +bindm = SUPER, mouse:273, resizewindow +bind = SUPER, quotedbl, workspace, 1 +bind = SUPER, guillemotleft, workspace, 2 +bind = SUPER, guillemotright, workspace, 3 +bind = SUPER, parenleft, workspace, 4 +bind = SUPER, parenright, workspace, 5 +bind = SUPER, at, workspace, 6 +bind = SUPER, plus, workspace, 7 +bind = SUPER, minus, workspace, 8 +bind = SUPER, slash, workspace, 9 +bind = SUPER, asterisk, workspace, 10 +bind = SUPER, mouse_down, workspace, e+1 +bind = SUPER, mouse_up, workspace, e-1 +bind = SUPER_SHIFT, quotedbl, movetoworkspace, 1 +bind = SUPER_SHIFT, guillemotleft, movetoworkspace, 2 +bind = SUPER_SHIFT, guillemotright, movetoworkspace, 3 +bind = SUPER_SHIFT, parenleft, movetoworkspace, 4 +bind = SUPER_SHIFT, parenright, movetoworkspace, 5 +bind = SUPER_SHIFT, at, movetoworkspace, 6 +bind = SUPER_SHIFT, plus, movetoworkspace, 7 +bind = SUPER_SHIFT, minus, movetoworkspace, 8 +bind = SUPER_SHIFT, slash, movetoworkspace, 9 +bind = SUPER_SHIFT, asterisk, movetoworkspace, 10 + +windowrulev2 = float,class:^(xfce-polkit)$ diff --git a/users/phundrak/config/waybar/config b/users/phundrak/config/waybar/config new file mode 100644 index 0000000..f18eb6b --- /dev/null +++ b/users/phundrak/config/waybar/config @@ -0,0 +1,167 @@ +// -*- mode: js-json -*- +{ + // "layer": "top", // Waybar at top layer + // "position": "bottom", // Waybar position (top|bottom|left|right) + "height": 24, // Waybar height (to be removed for auto height) + // "width": 1280, // Waybar width + "spacing": 2, // Gaps between modules (4px) + // Choose the order of the modules + "modules-left": ["hyprland/workspaces", "hyprland/submap", "hyprland/window"], + "modules-center": [], + "modules-right": ["idle_inhibitor", "mpd", "pulseaudio", "network", "cpu", + "memory", "temperature", "battery", "clock", "tray"], + // Modules configuration + // "sway/workspaces": { + // "disable-scroll": true, + // "all-outputs": true, + // "format": "{name}: {icon}", + // "format-icons": { + // "1": "", + // "2": "", + // "3": "", + // "4": "", + // "5": "", + // "urgent": "", + // "focused": "", + // "default": "" + // } + // }, + "keyboard-state": { + "numlock": true, + "capslock": true, + "format": "{name} {icon}", + "format-icons": { + "locked": "", + "unlocked": "" + } + }, + "sway/mode": { + "format": "{}" + }, + "sway/scratchpad": { + "format": "{icon} {count}", + "show-empty": false, + "format-icons": ["", ""], + "tooltip": true, + "tooltip-format": "{app}: {title}" + }, + "mpd": { + "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ", + "format-disconnected": "Disconnected ", + "format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ", + "unknown-tag": "N/A", + "interval": 2, + "consume-icons": { + "on": " " + }, + "random-icons": { + "off": " ", + "on": " " + }, + "repeat-icons": { + "on": " " + }, + "single-icons": { + "on": "1 " + }, + "state-icons": { + "paused": "", + "playing": "" + }, + "tooltip-format": "MPD (connected)", + "tooltip-format-disconnected": "MPD (disconnected)" + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "", + "deactivated": "" + } + }, + "tray": { + // "icon-size": 21, + "spacing": 10 + }, + "clock": { + // "timezone": "America/New_York", + "tooltip-format": "{:%Y %B}\n{calendar}", + "format-alt": "{:%Y-%m-%d}" + }, + "cpu": { + "format": "{usage}% ", + "tooltip": false + }, + "memory": { + "format": "{}% " + }, + "temperature": { + // "thermal-zone": 2, + // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input", + "critical-threshold": 80, + // "format-critical": "{temperatureC}°C {icon}", + "format": "{temperatureC}°C {icon}", + "format-icons": ["", "", ""] + }, + "backlight": { + // "device": "acpi_video1", + "format": "{percent}% {icon}", + "format-icons": ["", "", "", "", "", "", "", "", ""] + }, + "battery": { + "states": { + // "good": 95, + "warning": 30, + "critical": 15 + }, + "format": "{capacity}% {icon}", + "format-charging": "{capacity}% ", + "format-plugged": "{capacity}% ", + "format-alt": "{time} {icon}", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": ["", "", "", "", ""] + }, + "battery#bat2": { + "bat": "BAT2" + }, + "network": { + // "interface": "wlp2*", // (Optional) To force the use of this interface + "format-wifi": "{essid} ({signalStrength}%) ", + "format-ethernet": "{ipaddr}/{cidr} ", + "tooltip-format": "{ifname} via {gwaddr} ", + "format-linked": "{ifname} (No IP) ", + "format-disconnected": "Disconnected ⚠", + "format-alt": "{ifname}: {ipaddr}/{cidr}" + }, + "pulseaudio": { + // "scroll-step": 1, // %, can be a float + "format": "{volume}% {icon} {format_source}", + "format-bluetooth": "{volume}% {icon} {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": " {format_source}", + "format-source": "{volume}% ", + "format-source-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""] + }, + "on-click": "pavucontrol" + }, + "custom/media": { + "format": "{icon} {}", + "return-type": "json", + "max-length": 40, + "format-icons": { + "spotify": "", + "default": "🎜" + }, + "escape": true, + "exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null" // Script in resources folder + // "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name + } +} diff --git a/users/phundrak/config/waybar/style.css b/users/phundrak/config/waybar/style.css new file mode 100644 index 0000000..cf5c5fb --- /dev/null +++ b/users/phundrak/config/waybar/style.css @@ -0,0 +1,280 @@ +* { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: FontAwesome, Roboto, Helvetica, Arial, sans-serif; + font-size: 13px; +} + +window#waybar { + background-color: rgba(43, 48, 59, 0.5); + border-bottom: 3px solid rgba(100, 114, 125, 0.5); + color: #ffffff; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar.hidden { + opacity: 0.2; +} + +/* +window#waybar.empty { + background-color: transparent; +} +window#waybar.solo { + background-color: #FFFFFF; +} +*/ + +window#waybar.termite { + background-color: #3F3F3F; +} + +window#waybar.chromium { + background-color: #000000; + border: none; +} + +button { + /* Use box-shadow instead of border so the text isn't offset */ + box-shadow: inset 0 -3px transparent; + /* Avoid rounded borders under each button name */ + border: none; + border-radius: 0; +} + +/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ +button:hover { + background: inherit; + box-shadow: inset 0 -3px #ffffff; +} + +#workspaces button { + padding: 0 5px; + background-color: transparent; + color: #ffffff; +} + +#workspaces button:hover { + background: rgba(0, 0, 0, 0.2); +} + +#workspaces button.focused { + background-color: #64727D; + box-shadow: inset 0 -3px #ffffff; +} + +#workspaces button.urgent { + background-color: #eb4d4b; +} + +#mode { + background-color: #64727D; + border-bottom: 3px solid #ffffff; +} + +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#wireplumber, +#custom-media, +#tray, +#mode, +#idle_inhibitor, +#scratchpad, +#mpd { + padding: 0 10px; + color: #ffffff; +} + +#window, +#workspaces { + margin: 0 4px; +} + +/* If workspaces is the leftmost module, omit left margin */ +.modules-left > widget:first-child > #workspaces { + margin-left: 0; +} + +/* If workspaces is the rightmost module, omit right margin */ +.modules-right > widget:last-child > #workspaces { + margin-right: 0; +} + +#clock { + background-color: #64727D; +} + +#battery { + background-color: #ffffff; + color: #000000; +} + +#battery.charging, #battery.plugged { + color: #ffffff; + background-color: #26A65B; +} + +@keyframes blink { + to { + background-color: #ffffff; + color: #000000; + } +} + +#battery.critical:not(.charging) { + background-color: #f53c3c; + color: #ffffff; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; +} + +label:focus { + background-color: #000000; +} + +#cpu { + background-color: #2ecc71; + color: #000000; +} + +#memory { + background-color: #9b59b6; +} + +#disk { + background-color: #964B00; +} + +#backlight { + background-color: #90b1b1; +} + +#network { + background-color: #2980b9; +} + +#network.disconnected { + background-color: #f53c3c; +} + +#pulseaudio { + background-color: #f1c40f; + color: #000000; +} + +#pulseaudio.muted { + background-color: #90b1b1; + color: #2a5c45; +} + +#wireplumber { + background-color: #fff0f5; + color: #000000; +} + +#wireplumber.muted { + background-color: #f53c3c; +} + +#custom-media { + background-color: #66cc99; + color: #2a5c45; + min-width: 100px; +} + +#custom-media.custom-spotify { + background-color: #66cc99; +} + +#custom-media.custom-vlc { + background-color: #ffa000; +} + +#temperature { + background-color: #f0932b; +} + +#temperature.critical { + background-color: #eb4d4b; +} + +#tray { + background-color: #2980b9; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; + background-color: #eb4d4b; +} + +#idle_inhibitor { + background-color: #2d3436; +} + +#idle_inhibitor.activated { + background-color: #ecf0f1; + color: #2d3436; +} + +#mpd { + background-color: #66cc99; + color: #2a5c45; +} + +#mpd.disconnected { + background-color: #f53c3c; +} + +#mpd.stopped { + background-color: #90b1b1; +} + +#mpd.paused { + background-color: #51a37a; +} + +#language { + background: #00b093; + color: #740864; + padding: 0 5px; + margin: 0 5px; + min-width: 16px; +} + +#keyboard-state { + background: #97e1ad; + color: #000000; + padding: 0 0px; + margin: 0 5px; + min-width: 16px; +} + +#keyboard-state > label { + padding: 0 5px; +} + +#keyboard-state > label.locked { + background: rgba(0, 0, 0, 0.2); +} + +#scratchpad { + background: rgba(0, 0, 0, 0.2); +} + +#scratchpad.empty { + background-color: transparent; +} diff --git a/users/phundrak/gampo.nix b/users/phundrak/gampo.nix new file mode 100644 index 0000000..3a9e9c9 --- /dev/null +++ b/users/phundrak/gampo.nix @@ -0,0 +1,7 @@ +{ + imports = [./home.nix]; + home.phundrak.sshKey = { + content = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBPhP4p9KGk6jSOxJzBu+RzJPHI6baT0o+xrgPeNRwfq lucien@phundrak.com"; + file = "/home/phundrak/.ssh/id_ed25519.pub"; + }; +} diff --git a/users/phundrak/home.nix b/users/phundrak/home.nix new file mode 100644 index 0000000..369b767 --- /dev/null +++ b/users/phundrak/home.nix @@ -0,0 +1,99 @@ +{ + pkgs, + config, + inputs, + ... +}: { + imports = [ + ./light-home.nix + ./packages.nix + ../modules/emacs.nix + ../modules/kdeconnect.nix + ../modules/kitty.nix + ../modules/mbsync.nix + ../modules/mpd.nix + ../modules/mpv.nix + ../modules/wofi.nix + ../modules/yt-dlp.nix + ../modules/emoji.nix + ../modules/qt.nix + ]; + + config = let + emacsPkg = with pkgs; ((emacsPackagesFor emacsNativeComp).emacsWithPackages ( + epkgs: [ + epkgs.vterm + epkgs.mu4e + epkgs.pdf-tools + ] + )); + askpass = import ../scripts/askpass.nix {inherit pkgs;}; + launchWithEmacsclient = import ../scripts/launch-with-emacsclient.nix { + inherit pkgs; + emacsPackage = emacsPkg; + }; + in { + sops.secrets = { + emailPassword = {}; + "mopidy/bandcamp" = {}; + "mopidy/spotify" = {}; + }; + + home.sessionVariables = { + EDITOR = "${emacsPkg}/bin/emacsclient -c -a ${emacsPkg}/bin/emacs"; + LAUNCH_EDITOR = "${launchWithEmacsclient}/bin/launch-with-emacsclient"; + SUDO_ASKPASS = "${askpass}/bin/askpass"; + LSP_USE_PLISTS = "true"; + }; + + modules = { + emacs = { + enable = true; + service = true; + package = emacsPkg; + }; + shell.starship.jjIntegration = true; + bat.extras = true; + packages.emacsPackage = emacsPkg; + mopidy.enable = true; + + mbsync = { + enable = true; + passwordFile = config.sops.secrets.emailPassword.path; + }; + ssh = { + enable = true; + hosts = config.sops.secrets."ssh/hosts".path; + }; + vcs.git = { + browser = "${inputs.zen-browser.packages.${pkgs.system}.default}/bin/zen"; + emacs = { + integration = true; + pkg = emacsPkg; + }; + sendmail = { + enable = true; + passwordFile = config.sops.secrets.emailPassword.path; + }; + }; + }; + + programs = { + zsh.enableVteIntegration = true; + mu.enable = true; + obs-studio = { + enable = true; + plugins = with pkgs; [ + obs-studio-plugins.input-overlay + obs-studio-plugins.obs-backgroundremoval + obs-studio-plugins.obs-mute-filter + obs-studio-plugins.obs-pipewire-audio-capture + obs-studio-plugins.obs-source-clone + obs-studio-plugins.obs-source-record + obs-studio-plugins.obs-tuna + ]; + }; + }; + manual.html.enable = true; + }; +} diff --git a/users/phundrak/light-home.nix b/users/phundrak/light-home.nix new file mode 100644 index 0000000..ccba29c --- /dev/null +++ b/users/phundrak/light-home.nix @@ -0,0 +1,68 @@ +{ + lib, + pkgs, + config, + ... +}: +with lib; let + cfg = config.home.phundrak; +in { + imports = [../modules]; + + options.home.phundrak = { + sshKey = { + content = mkOption { + type = types.nullOr types.str; + example = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGj+J6N6SO+4P8dOZqfR1oiay2yxhhHnagH52avUqw5h"; + default = null; + }; + file = mkOption { + type = with types; nullOr path; + default = "/home/phundrak/.ssh/id_ed25519.pub"; + }; + }; + }; + + config = { + nixpkgs.config.allowUnfree = true; + + sops = { + defaultSopsFile = ../../secrets/secrets.yaml; + defaultSopsFormat = "yaml"; + secrets."ssh/hosts" = {}; + age = { + # automatically import user SSH keys as age keys + sshKeyPaths = [ + "/home/phundrak/.ssh/id_ed25519" + ]; + # this will use an age key that is expected to already be in the filesystem + # keyFile = "/home/phundrak/.config/sops/age/keys.txt"; + keyFile = "/home/phundrak/.local/sops-nix/key.txt"; + # generate a new key if the key specified above does not exist + generateKey = true; + }; + }; + + home = { + username = "phundrak"; + homeDirectory = "/home/phundrak"; + packages = [pkgs.tree pkgs.ncdu]; + stateVersion = "24.11"; # Please read the comment before changing. + }; + + modules = { + shell.starship.enable = true; + vcs = { + git.enable = true; + jj.enable = true; + publicKey = cfg.sshKey; + }; + ssh = { + enable = true; + hosts = config.sops.secrets."ssh/hosts".path; + }; + }; + + manual.manpages.enable = true; + }; +} diff --git a/users/phundrak/marpa.nix b/users/phundrak/marpa.nix new file mode 100644 index 0000000..3a9e9c9 --- /dev/null +++ b/users/phundrak/marpa.nix @@ -0,0 +1,7 @@ +{ + imports = [./home.nix]; + home.phundrak.sshKey = { + content = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBPhP4p9KGk6jSOxJzBu+RzJPHI6baT0o+xrgPeNRwfq lucien@phundrak.com"; + file = "/home/phundrak/.ssh/id_ed25519.pub"; + }; +} diff --git a/users/phundrak/packages.nix b/users/phundrak/packages.nix new file mode 100644 index 0000000..ae5ef83 --- /dev/null +++ b/users/phundrak/packages.nix @@ -0,0 +1,110 @@ +{ + pkgs, + inputs, + lib, + config, + ... +}: +with lib; let + cfg = config.modules.packages; +in { + options.modules.packages.emacsPackage = mkOption { + type = types.package; + default = pkgs.emacs; + }; + config.home.packages = with pkgs; let + scripts = import ../scripts/scripts.nix { + inherit pkgs; + config.emacsPkg = cfg.emacsPackage; + }; + in + [ + flatpak + + # LSP server for Nix + nil + + # Terminal stuff + duf + ffmpeg + ripgrep-all + unzip + + # Fonts + #nerdfonts + noto-fonts-cjk-sans + noto-fonts-cjk-serif + tibetan-machine + + # Browsers + amfora + + # Media + ani-cli + audacity + plexamp + plex-media-player + spicetify-cli + spotify + spotify-tray + + # Social + vesktop # Discord alternative that works well with wayland + element-desktop + signal-desktop-bin + + # Misc + bitwarden + gplates + libnotify + nextcloud-client + onlyoffice-bin + scrcpy + syncthing + watchmate + inputs.zen-browser.packages.${system}.default + + # Games + atlauncher + heroic + modrinth-app + openttd-jgrpp + moonlight-qt + + # Emacs stuff + emacs-all-the-icons-fonts + + # Gnome stuff + gnome-tweaks + gnomeExtensions.docker + gnomeExtensions.syncthing-indicator + gnomeExtensions.tray-icons-reloaded + gthumb + + # Graphics + inkscape + gimp + gimpPlugins.fourier + gimpPlugins.farbfeld + + # Dev + devenv + dive # A tool for exploring each layer in a docker image + grype # Vulnerability scanner for container images and filesystems + podman-desktop + podman-compose + python3 # for Emacs and LSP + tectonic # better LaTeX engine + virt-manager + zeal + + # # It is sometimes useful to fine-tune packages, for example, by applying + # # overrides. You can do that directly here, just don't forget the + # # parentheses. Maybe you want to install Nerd Fonts with a limited number of + # # fonts? + # (pkgs.nerdfonts.override { fonts = [ "FantasqueSansMono" ]; }) + + # Custom scripts + ] + ++ scripts; +} diff --git a/users/phundrak/programs.nix b/users/phundrak/programs.nix new file mode 100644 index 0000000..d0aa138 --- /dev/null +++ b/users/phundrak/programs.nix @@ -0,0 +1,12 @@ +{ + imports = [ + ../modules/emacs.nix + ../modules/kdeconnect.nix + ../modules/kitty.nix + ../modules/mbsync.nix + ../modules/mpd.nix + ../modules/mpv.nix + ../modules/wofi.nix + ../modules/yt-dlp.nix + ]; +} diff --git a/users/phundrak/tilo.nix b/users/phundrak/tilo.nix new file mode 100644 index 0000000..0c36943 --- /dev/null +++ b/users/phundrak/tilo.nix @@ -0,0 +1,8 @@ +{ + imports = [./light-home.nix]; + home.phundrak.sshKey = { + content = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILw9oiK8tZ5Vpz82RaRLpITU8qeJrT2hjvudGEDQu2QW lucien@phundrak.com"; + file = "/home/phundrak/.ssh/id_ed25519.pub"; + }; + modules.nh.flake = "/tank/phundrak/nixos"; +} diff --git a/users/scripts/askpass.nix b/users/scripts/askpass.nix new file mode 100644 index 0000000..c830fe4 --- /dev/null +++ b/users/scripts/askpass.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: +pkgs.writeShellScriptBin "askpass" '' + ${pkgs.wofi}/bin/wofi -d -P -L 1 -p "$(printf $1 | sed s/://)"'' diff --git a/users/scripts/backup.nix b/users/scripts/backup.nix new file mode 100644 index 0000000..f6de86b --- /dev/null +++ b/users/scripts/backup.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: +pkgs.writeShellScriptBin "backup" '' + cp -r "$1" "$1.bak.$(date +%Y%m%d%H%M%S)"'' diff --git a/users/scripts/hyprland-autostart.nix b/users/scripts/hyprland-autostart.nix new file mode 100644 index 0000000..9bf9942 --- /dev/null +++ b/users/scripts/hyprland-autostart.nix @@ -0,0 +1,4 @@ +{pkgs, ...}: +pkgs.writeShellScriptBin "hyprland-autostart" '' + ${pkgs.waybar}/bin/waybar & + ${pkgs.wlsunset}/bin/wlsunset -l 48.5 -L 2.2 -d 1500'' diff --git a/users/scripts/keygen.nix b/users/scripts/keygen.nix new file mode 100644 index 0000000..bcdf9ea --- /dev/null +++ b/users/scripts/keygen.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: +pkgs.writeShellScriptBin "keygen" +"tr -cd '[:alnum:]' < /dev/urandom | fold -w 64 | head -n 1 | tr -d '\n'" diff --git a/users/scripts/launch-with-emacsclient.nix b/users/scripts/launch-with-emacsclient.nix new file mode 100644 index 0000000..ed48acd --- /dev/null +++ b/users/scripts/launch-with-emacsclient.nix @@ -0,0 +1,10 @@ +{ + pkgs, + emacsPackage, + ... +}: +pkgs.writeShellScriptBin "launch-with-emacsclient" '' + filename="$1" + line="$2" + column="$3" + ${emacsPackage}/bin/emacsclient +$line:$column "$filename"'' diff --git a/users/scripts/mp42webm.nix b/users/scripts/mp42webm.nix new file mode 100644 index 0000000..6a88463 --- /dev/null +++ b/users/scripts/mp42webm.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: +pkgs.writeShellScriptBin "mp42webm" '' + ${pkgs.ffmpeg}/bin/ffmpeg -i "$1" -c:v libvpx -crf 10 -b:v 1M -c:a libvorbis "$1".webm'' diff --git a/users/scripts/scripts.nix b/users/scripts/scripts.nix new file mode 100644 index 0000000..31e6f3f --- /dev/null +++ b/users/scripts/scripts.nix @@ -0,0 +1,18 @@ +{ + config, + pkgs, + ... +}: let + askpass = import ./askpass.nix {inherit pkgs;}; +in [ + askpass + (import ./backup.nix {inherit pkgs;}) + (import ./hyprland-autostart.nix {inherit pkgs;}) + (import ./keygen.nix {inherit pkgs;}) + (import ./launch-with-emacsclient.nix { + inherit pkgs; + emacsPackage = config.emacsPkg; + }) + (import ./mp42webm.nix {inherit pkgs;}) + (import ./sshbind.nix {inherit pkgs;}) +] diff --git a/users/scripts/sshbind.nix b/users/scripts/sshbind.nix new file mode 100644 index 0000000..ab5630d --- /dev/null +++ b/users/scripts/sshbind.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: +pkgs.writeShellScriptBin "sshbind" '' + ssh -L "$1:$3:$1" "$2" -N'' diff --git a/users/scripts/ytplay.nix b/users/scripts/ytplay.nix new file mode 100644 index 0000000..fd03d25 --- /dev/null +++ b/users/scripts/ytplay.nix @@ -0,0 +1,18 @@ +{pkgs, ...}: let + rofi = pkgs.rofi-wayland; +in + pkgs.writeShellScriptBin "ytplay" '' + URL=$(${rofi}/bin/rofi -dmenu -i -p "Video URL") + if [ -z "$URL" ]; then + echo "You need to provide a URL" + exit 1 + fi + RESOLUTION_CHOICE=$(${pkgs.yt-dlp}/bin/yt-dlp --list-formats "$URL" | \ + grep -E "webm.*[0-9]+x[0-9]" | \ + awk '{print $3 " " $1}' | \ + sort -gu | \ + ${rofi}/bin/rofi -dmenu -i -p "Resolution") + mapfile -t RESOLUTION <<< "$RESOLUTION_CHOICE" + RESOLUTION_CODE=''${RESOLUTION[0]} + ${pkgs.mpv}/bin/mpv --ytdl-format="''${RESOLUTION_CODE}+bestaudio/best" "$URL" + ''