diff --git a/CMakeLists.txt b/CMakeLists.txt
index 862e4f1a..291a6f2e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -312,8 +312,6 @@ else()
 	if(NOT DEFINED SUNSHINE_EXECUTABLE_PATH)
 		set(SUNSHINE_EXECUTABLE_PATH "sunshine")
 	endif()
-	configure_file(gen-deb.in gen-deb @ONLY)
-	configure_file(gen-rpm.in gen-rpm @ONLY)
 	configure_file(sunshine.desktop.in sunshine.desktop @ONLY)
 	configure_file(sunshine.service.in sunshine.service @ONLY)
 endif()
@@ -448,3 +446,63 @@ foreach(flag IN LISTS SUNSHINE_COMPILE_OPTIONS)
 endforeach()
 
 target_compile_options(sunshine PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${SUNSHINE_COMPILE_OPTIONS}>;$<$<COMPILE_LANGUAGE:CUDA>:${SUNSHINE_COMPILE_OPTIONS_CUDA};-std=c++17>)
+
+#############
+# CPACK
+####
+
+# Add all assets dependencies 
+install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/web" DESTINATION ".")
+install(FILES "${SUNSHINE_ASSETS_DIR}/sunshine.conf" DESTINATION ".")
+if(WIN32) # TODO: test
+	install(TARGETS sunshine RUNTIME DESTINATION ".")
+
+	install(FILES "${SUNSHINE_ASSETS_DIR}/apps_windows.json" DESTINATION ".")
+	install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/directx" DESTINATION "shaders")
+endif()
+if(APPLE) # TODO: test
+	install(TARGETS sunshine RUNTIME DESTINATION ".")
+
+	install(FILES "${SUNSHINE_ASSETS_DIR}/apps_mac.json" DESTINATION ".")
+	# TODO: info.plist ??
+endif()
+if(UNIX AND NOT APPLE)
+	install(FILES "${SUNSHINE_ASSETS_DIR}/apps_linux.json" DESTINATION ".")
+	install(FILES "${SUNSHINE_ASSETS_DIR}/85-sunshine-rules.rules" DESTINATION "/etc/udev/rules.d")
+	install(TARGETS sunshine RUNTIME DESTINATION "/usr/bin")
+	install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "/usr/lib/systemd/user")
+	install(DIRECTORY "${SUNSHINE_ASSETS_DIR}/shaders/opengl" DESTINATION "shaders")
+
+	# Pre and post install
+	set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA 
+		"${SUNSHINE_ASSETS_DIR}/linux-deb/preinst;${SUNSHINE_ASSETS_DIR}/linux-deb/postinst;${SUNSHINE_ASSETS_DIR}/linux-deb/conffiles")
+	set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/preinst")
+	set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${SUNSHINE_ASSETS_DIR}/linux-deb/postinst")
+endif()
+
+# Common options
+set(CPACK_PACKAGE_NAME "SunshineStream")
+set(CPACK_PACKAGE_VENDOR "CMake.org")
+set(CPACK_PACKAGE_CONTACT "https://github.com/SunshineStream/Sunshine")
+set(CPACK_DEBIAN_PACKAGE_MAINTAINER "https://github.com/SunshineStream/Sunshine")
+set(CPACK_PACKAGE_DESCRIPTION "Gamestream host for Moonlight")
+set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/SunshineStream/Sunshine")
+set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE)
+set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/sunshine.png)
+set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}_${VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
+set(CPACK_STRIP_FILES YES)
+
+# Installation destination dir
+if(NOT WIN32)
+	set(CPACK_SET_DESTDIR true)
+endif()
+if(UNIX AND NOT APPLE)
+	set(CMAKE_INSTALL_PREFIX "/etc/sunshine")
+endif()
+
+## DEB
+set(CPACK_DEB_COMPONENT_INSTALL ON)
+set(CPACK_DEBIAN_PACKAGE_DEPENDS "libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2")
+set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF)
+
+include(CPack)
\ No newline at end of file
diff --git a/assets/linux-deb/conffiles b/assets/linux-deb/conffiles
new file mode 100644
index 00000000..78176a81
--- /dev/null
+++ b/assets/linux-deb/conffiles
@@ -0,0 +1,2 @@
+/etc/sunshine/sunshine.conf
+/etc/sunshine/apps_linux.json
diff --git a/assets/linux-deb/postinst b/assets/linux-deb/postinst
new file mode 100644
index 00000000..cf66231f
--- /dev/null
+++ b/assets/linux-deb/postinst
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+export GROUP_INPUT=input
+
+if [ -f /etc/group ]; then
+        if ! grep -q $GROUP_INPUT /etc/group; then
+                echo "Creating group $GROUP_INPUT"
+
+                groupadd $GROUP_INPUT
+        fi
+else
+        echo "Warning: /etc/group not found"
+fi
+
+if [ -f /etc/sunshine/sunshine.conf.old ]; then
+	echo "Restoring old sunshine.conf"
+	mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf
+fi
+
+if [ -f /etc/sunshine/apps_linux.json.old ]; then
+	echo "Restoring old apps_linux.json"
+	mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json
+fi
+
+# Update permissions on config files for Web Manager
+if [ -f /etc/sunshine/apps_linux.json ]; then
+	echo "chmod 666 /etc/sunshine/apps_linux.json"
+	chmod 666 /etc/sunshine/apps_linux.json
+fi
+
+if [ -f /etc/sunshine/sunshine.conf ]; then
+	echo "chmod 666 /etc/sunshine/sunshine.conf"
+	chmod 666 /etc/sunshine/sunshine.conf
+fi
+
+# Ensure Sunshine can grab images from KMS
+path_to_setcap=$(which setcap)
+if [ -x "$path_to_setcap" ] ; then
+  echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine"
+	$path_to_setcap cap_sys_admin+p $(readlink -f /usr/bin/sunshine)
+fi
diff --git a/assets/linux-deb/preinst b/assets/linux-deb/preinst
new file mode 100644
index 00000000..515d1a34
--- /dev/null
+++ b/assets/linux-deb/preinst
@@ -0,0 +1,9 @@
+#!/bin/sh
+#Store backup for old config files to prevent it from being overwritten
+if [ -f /etc/sunshine/sunshine.conf ]; then
+        cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old
+fi
+
+if [ -f /etc/sunshine/apps_linux.json ]; then
+        cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old
+fi
diff --git a/gen-deb.in b/gen-deb.in
deleted file mode 100755
index 25ca3609..00000000
--- a/gen-deb.in
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/bin/sh
-
-if [ ! "@SUNSHINE_UNDEFINED_VARIABLE@" = "" ]; then
-	echo "Please run gen-deb generated by cmake inside the build directory"
-	exit 1
-fi
-
-if [ -d package-deb ]; then
-	echo "package-deb already exists: It will be replaced"
-	rm -rf package-deb
-fi
-
-export DEBIAN=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/DEBIAN
-export RULES=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/etc/udev/rules.d
-export BIN=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/usr/bin
-export SERVICE=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/usr/lib/systemd/user
-export ASSETS=@CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine/etc/sunshine
-
-mkdir -p $DEBIAN
-mkdir -p $RULES
-mkdir -p $BIN
-mkdir -p $ASSETS/shaders
-mkdir -p $SERVICE
-
-if [ ! -f sunshine ]; then
-	echo "Error: Can't find sunshine"
-	exit 1
-fi
-
-cat << 'EOF' > $DEBIAN/conffiles
-/etc/sunshine/sunshine.conf
-/etc/sunshine/apps_linux.json
-EOF
-
-cat << 'EOF' > $DEBIAN/control
-Package: sunshine
-Architecture: amd64
-Maintainer: @loki
-Priority: optional
-Version: @PROJECT_VERSION@
-Depends: libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0 | libboost-thread1.74.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0 | libboost-filesystem1.74.0, libboost-log1.67.0 | libboost-log1.71.0 | libboost-log1.74.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2, libcap2
-Description: Gamestream host for Moonlight
-EOF
-
-cat << 'EOF' > $DEBIAN/preinst
-#Store backup for old config files to prevent it from being overwritten
-if [ -f /etc/sunshine/sunshine.conf ]; then
-        cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old
-fi
-
-if [ -f /etc/sunshine/apps_linux.json ]; then
-        cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old
-fi
-EOF
-
-cat << 'EOF' > $DEBIAN/postinst
-#!/bin/sh
-
-export GROUP_INPUT=input
-
-if [ -f /etc/group ]; then
-        if ! grep -q $GROUP_INPUT /etc/group; then
-                echo "Creating group $GROUP_INPUT"
-
-                groupadd $GROUP_INPUT
-        fi
-else
-        echo "Warning: /etc/group not found"
-fi
-
-if [ -f /etc/sunshine/sunshine.conf.old ]; then
-	echo "Restoring old sunshine.conf"
-	mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf
-fi
-
-if [ -f /etc/sunshine/apps_linux.json.old ]; then
-	echo "Restoring old apps_linux.json"
-	mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json
-fi
-
-# Update permissions on config files for Web Manager
-if [ -f /etc/sunshine/apps_linux.json ]; then
-	echo "chmod 666 /etc/sunshine/apps_linux.json"
-	chmod 666 /etc/sunshine/apps_linux.json
-fi
-
-if [ -f /etc/sunshine/sunshine.conf ]; then
-	echo "chmod 666 /etc/sunshine/sunshine.conf"
-	chmod 666 /etc/sunshine/sunshine.conf
-fi
-
-# Ensure Sunshine can grab images from KMS
-path_to_setcap=$(which setcap)
-if [ -x "$path_to_setcap" ] ; then
-  echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine"
-	$path_to_setcap cap_sys_admin+p /usr/bin/sunshine
-fi
-EOF
-
-cat << 'EOF' > $RULES/85-sunshine-rules.rules
-KERNEL=="uinput", GROUP="input", MODE="0660"
-EOF
-
-cp sunshine $BIN/sunshine
-cp @CMAKE_CURRENT_SOURCE_DIR@/assets/apps_linux.json $ASSETS/apps_linux.json
-cp @CMAKE_CURRENT_SOURCE_DIR@/assets/sunshine.conf $ASSETS/sunshine.conf
-cp @CMAKE_CURRENT_BINARY_DIR@/sunshine.service $SERVICE/sunshine.service
-cp -r @CMAKE_CURRENT_SOURCE_DIR@/assets/web $ASSETS/web
-cp -r @CMAKE_CURRENT_SOURCE_DIR@/assets/shaders/opengl $ASSETS/shaders/opengl
-
-chmod 755 $DEBIAN/postinst
-chmod 755 $DEBIAN/preinst
-chmod 755 $BIN/sunshine
-chmod 644 $RULES/85-sunshine-rules.rules
-chmod 666 $ASSETS/apps_linux.json
-chmod 666 $ASSETS/sunshine.conf
-
-cd package-deb
-if fakeroot dpkg-deb --build sunshine; then
-	echo "generated debian package: @CMAKE_CURRENT_BINARY_DIR@/package-deb/sunshine.deb"
-fi
-cd ..
-
diff --git a/gen-rpm.in b/gen-rpm.in
deleted file mode 100755
index 792a3895..00000000
--- a/gen-rpm.in
+++ /dev/null
@@ -1,179 +0,0 @@
-#!/bin/sh
-
-# Export filepaths
-export BUILDDIR=@CMAKE_CURRENT_SOURCE_DIR@/build
-export BUILDROOT=~/rpmbuild/
-export RPMSRC=~/rpmbuild/SOURCES
-export RPMSPEC=~/rpmbuild/SPECS
-export RPMBUILD=~/rpmbuild/BUILD
-
-# Check for Docker switch
-if [ "$1" == "-d" ]; then
-	export DOCKERSTATUS=TRUE
-else
-	export DOCKERSTATUS=FALSE
-fi
-
-# Check if user's rpmbuild folder is there, if so, temoprairly rename it.
-if [ -d ~/rpmbuild ]; then
-	echo "Backing up rpmbuild"
-	~/rpmbuild ~/rpmbuild.bkp
-	export RPMBUILDEXISTS=TRUE
-else
-	export RPMBUILDEXISTS=FALSE
-fi
-
-# Create rpmbuild folder structure
-mkdir ~/rpmbuild
-mkdir ~/rpmbuild/BUILD
-mkdir ~/rpmbuild/BUILDROOT
-mkdir ~/rpmbuild/RPMS
-mkdir ~/rpmbuild/SOURCES
-mkdir ~/rpmbuild/SPECS
-mkdir ~/rpmbuild/SRPMS
-
-# Create sunshine .spec file with preinstall and postinstall scripts
-cat << 'EOF' > $RPMSPEC/sunshine.spec
-Name:           sunshine
-Version:        @PROJECT_VERSION@
-Release:        1%{?dist}
-Summary:        An NVIDIA Gamestream-compatible hosting server
-BuildArch:      x86_64
-
-License:        GPLv3
-URL:            https://github.com/SunshineStream/Sunshine
-Source0:        sunshine-@PROJECT_VERSION@_bin.tar.gz
-
-Requires:       systemd ffmpeg rpmfusion-free-release
-
-%description
-An NVIDIA Gamestream-compatible hosting server
-
-%pre
-#!/bin/sh
-
-# Sunshine Pre-Install Script
-# Store backup for old config files to prevent it from being overwritten
-if [ -f /etc/sunshine/sunshine.conf ]; then
-        cp /etc/sunshine/sunshine.conf /etc/sunshine/sunshine.conf.old
-fi
-
-if [ -f /etc/sunshine/apps_linux.json ]; then
-        cp /etc/sunshine/apps_linux.json /etc/sunshine/apps_linux.json.old
-fi
-
-%post
-#!/bin/sh
-
-# Sunshine Post-Install Script
-export GROUP_INPUT=input
-
-if [ -f /etc/group ]; then
-        if ! grep -q $GROUP_INPUT /etc/group; then
-                echo "Creating group $GROUP_INPUT"
-
-                groupadd $GROUP_INPUT
-        fi
-else
-        echo "Warning: /etc/group not found"
-fi
-
-if [ -f /etc/sunshine/sunshine.conf.old ]; then
-	echo "Restoring old sunshine.conf"
-	mv /etc/sunshine/sunshine.conf.old /etc/sunshine/sunshine.conf
-fi
-
-if [ -f /etc/sunshine/apps_linux.json.old ]; then
-	echo "Restoring old apps_linux.json"
-	mv /etc/sunshine/apps_linux.json.old /etc/sunshine/apps_linux.json
-fi
-
-# Update permissions on config files for Web Manager
-if [ -f /etc/sunshine/apps_linux.json ]; then
-	echo "chmod 666 /etc/sunshine/apps_linux.json"
-	chmod 666 /etc/sunshine/apps_linux.json
-fi
-
-if [ -f /etc/sunshine/sunshine.conf ]; then
-	echo "chmod 666 /etc/sunshine/sunshine.conf"
-	chmod 666 /etc/sunshine/sunshine.conf
-fi
-
-# Ensure Sunshine can grab images from KMS
-path_to_setcap=$(which setcap)
-if [ -x "$path_to_setcap" ] ; then
-  echo "$path_to_setcap cap_sys_admin+p /usr/bin/sunshine"
-	$path_to_setcap cap_sys_admin+p /usr/bin/sunshine
-fi
-
-%prep
-%setup -q
-
-%install
-rm -rf $RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/%{_bindir}
-mkdir -p $RPM_BUILD_ROOT/etc/sunshine
-mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/user
-mkdir -p $RPM_BUILD_ROOT/usr/share/applications
-mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
-
-cp sunshine $RPM_BUILD_ROOT/%{_bindir}/sunshine
-cp sunshine.conf $RPM_BUILD_ROOT/etc/sunshine/sunshine.conf
-cp apps_linux.json $RPM_BUILD_ROOT/etc/sunshine/apps_linux.json
-cp sunshine.service $RPM_BUILD_ROOT/usr/lib/systemd/user/sunshine.service
-cp sunshine.desktop $RPM_BUILD_ROOT/usr/share/applications/sunshine.desktop
-cp 85-sunshine-rules.rules $RPM_BUILD_ROOT/etc/udev/rules.d/85-sunshine-rules.rules
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%{_bindir}/sunshine
-/usr/lib/systemd/user/sunshine.service
-/etc/sunshine/sunshine.conf
-/etc/sunshine/apps_linux.json
-/usr/share/applications/sunshine.desktop
-/etc/udev/rules.d/85-sunshine-rules.rules
-
-%changelog
-* Sat Mar 12 2022 h <65380846+thatsysadmin@users.noreply.github.com>
-- Initial packaging of Sunshine.
-EOF
-
-# Copy over sunshine binary and supplemental files into rpmbuild/BUILD/
-mkdir genrpm
-mkdir genrpm/sunshine-@PROJECT_VERSION@
-cp sunshine-@PROJECT_VERSION@ genrpm/sunshine-@PROJECT_VERSION@/sunshine
-cp sunshine.service genrpm/sunshine-@PROJECT_VERSION@/sunshine.service
-cp sunshine.desktop genrpm/sunshine-@PROJECT_VERSION@/sunshine.desktop
-cp @CMAKE_CURRENT_SOURCE_DIR@/assets/sunshine.conf genrpm/sunshine-@PROJECT_VERSION@/sunshine.conf
-cp @CMAKE_CURRENT_SOURCE_DIR@/assets/apps_linux.json genrpm/sunshine-@PROJECT_VERSION@/apps_linux.json
-cp @CMAKE_CURRENT_SOURCE_DIR@/assets/85-sunshine-rules.rules genrpm/sunshine-@PROJECT_VERSION@/85-sunshine-rules.rules
-cd genrpm
-
-# tarball everything as if it was a source file for rpmbuild
-tar --create --file sunshine-@PROJECT_VERSION@_bin.tar.gz sunshine-@PROJECT_VERSION@/
-cp sunshine-@PROJECT_VERSION@_bin.tar.gz ~/rpmbuild/SOURCES
-
-# Use rpmbuild to build the RPM package.
-rpmbuild -bb $RPMSPEC/sunshine.spec
-
-# Check if running in a CT
-if [ "$DOCKERSTATUS" == "FALSE" ]; then
-	# Move the completed RPM into the cmake build folder
-	mv ~/rpmbuild/RPMS/x86_64/sunshine-@PROJECT_VERSION@-1.fc*.x86_64.rpm @CMAKE_CURRENT_BINARY_DIR@/
-	echo "Moving completed RPM package into CMake build folder."
-elif [ "$DOCKERSTATUS" == "TRUE" ]; then
-	# Move into pickup location
-	mkdir -p /root/sunshine-build/package-rpm/
-	mv ~/rpmbuild/RPMS/x86_64/sunshine-@PROJECT_VERSION@-1.fc*.x86_64.rpm /root/sunshine-build/package-rpm/sunshine.rpm
-	echo "Moving completed RPM package for pickup."
-fi
-
-# Clean up; delete the rpmbuild folder we created and move back the original one
-if [ "$RPMBUILDEXISTS" == "TRUE" ]; then
-        echo "Removing and replacing original rpmbuild folder."
-        rm -rf ~/rpmbuild
-        mv ~/rpmbuild.bkp ~/rpmbuild
-fi
-exit 0