When using SQLite driver with Vapor, we have to install another package, or the project won't compile.
$ sudo apt install libsqlite3-dev
When using SQLite driver with Vapor, we have to install another package, or the project won't compile.
$ sudo apt install libsqlite3-dev
My server was 1GB RAM VPS in Ubuntu 20.04 LTS. And I developed vapor on my iMac 5K. So the first thing I did was to create a Linux client.
I prefer VMWare Fusion. As it was free for open source use. I tried VirtualBox, it ran slow with iMac 5K. Parallels Desktop was also good. But it was too expensive.
After all, now you should have a working Ubuntu 20.04.
$ sudo apt update
$ sudo apt install \
binutils \
git \
gnupg2 \
libc6-dev \
libcurl4 \
libedit2 \
libgcc-9-dev \
libpython2.7 \
libsqlite3-0 \
libstdc++-9-dev \
libxml2 \
libz3-dev \
pkg-config \
tzdata \
zlib1g-dev
$ sudo apt install nginx
Open Firefox with "localhost".
Download the latest release Swift Toolchain for Ubuntu 20.04.
$ cd Downloads/
$ wget https://download.swift.org/swift-5.5.1-release/ubuntu2004/swift-5.5.1-RELEASE/swift-5.5.1-RELEASE-ubuntu20.04.tar.gz
$ tar xzf swift-5.5.1-RELEASE-ubuntu20.04.tar.gz
$ vi ~/.bashrc
Append
export PATH=/home/zhaoxin/Downloads/swift-5.5.1-RELEASE-ubuntu20.04/usr/bin:”${PATH}”
Save and Quit。
Quit Terminal and Open it again. Type
$ swift --version
Swift version 5.5.1 (swift-5.5.1-RELEASE)
Target: x86_64-unknown-linux-gnu
$ cd ~/Downloads
$ git clone https://github.com/vapor/toolbox.git
$ cd toolbox/
$ git checkout 18.3.3
$ swift build -c release --disable-sandbox --enable-test-discovery
$ sudo mv .build/release/vapor /usr/local/bin
When compile, Vapor needs at least 2GB RAM. So for some VPS with only 1GB RAM, you will get fatalError when compile. You can check RAM with command
$ free -h
total used free shared buff/cache available
Mem: 3.8Gi 1.2Gi 447Mi 14Mi 2.1Gi 2.3Gi
Swap: 923Mi 1.0Mi 921Mi
Above is my VMWare Fusion client. However, for you VPS, you may get a result as below
$ free -h
total used free shared buff/cache available
Mem: 981Mi 215Mi 95Mi 2.0Mi 670Mi 575Mi
Swap: 0B 0B 0B
If that is your case, you must create a swap or you get your Vapor project compiled.
$ sudo swapon --show
You may get nothing shown as there was no swap for you VPS. Check you disk free space.
df -h
Filesystem Size Used Avail Use% Mounted on
udev 447M 0 447M 0% /dev
tmpfs 99M 944K 98M 1% /run
/dev/vda1 24G 12G 11G 51% /
tmpfs 491M 0 491M 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 491M 0 491M 0% /sys/fs/cgroup
/dev/loop0 43M 43M 0 100% /snap/certbot/1514
/dev/loop1 43M 43M 0 100% /snap/certbot/1582
/dev/loop2 100M 100M 0 100% /snap/core/11798
/dev/loop3 100M 100M 0 100% /snap/core/11993
/dev/loop4 62M 62M 0 100% /snap/core20/1169
/dev/loop5 62M 62M 0 100% /snap/core20/1242
tmpfs 99M 0 99M 0% /run/user/0
Look at "/dev/vda1 24G 12G 11G 51% /", That meant you had 11G free space.
Create swap file.
$ sudo fallocate -l 1G /swapfile
$ ls -lh /swapfile
-rw-r--r-- 1 root root 1.0G Apr 25 11:14 /swapfile
Enable swap file
$ sudo chmod 600 /swapfile
$ ls -lh /swapfile
-rw------- 1 root root 1.0G Apr 25 11:14 /swapfile
$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=6e965805-2ab9-450f-aed6-577e74089dbf
$ sudo swapon /swapfile
$ sudo swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 1024M 0B -2
$ free - h
total used free shared buff/cache available
Mem: 1004716 166880 147152 2724 690684 643212
Swap: 1048572 5940 1042632
Save Swap File
$ sudo cp /etc/fstab /etc/fstab.bak
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
$ cd
$ mkdir vapor
$ cd vapor
$ git config --global user.email "you@email.com"
$ git config --global user.name "Your Name"
$ vapor new hello -n
$ cd hello/
$ swift run
...
[1686/1686] Build complete!
[ NOTICE ] Server starting on http://127.0.0.1:8080
Open Firefox and type "localhost:8080".
$ cd /etc/nginx/sites-available/
$ sudo cp default default.bak
$ sudo rm default
$ sudo vi default
Copy and paste below to default and save.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
try_files $uri @proxy;
location @proxy {
proxy_pass http://127.0.0.1:8080;
proxy_pass_header Server;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Server;
proxy_connect_timeout 3s;
proxy_read_timeout 10s;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
}
}
Restart NGINX.
sudo systemctl restart nginx
$ sudo apt install supervisor
$ cd /etc/supervisor/conf.d/
$ sudo vi hello.conf
Copy and paste below code and save.
[program:hello]
command=/home/zhaoxin/vapor/hello/.build/debug/Run serve --env production
directory=/home/zhaoxin/vapor/hello
user=zhaoxin
stdout_logfile=/var/log/supervisor/%(program_name)-stdout.log
stderr_logfile=/var/log/supervisor/%(program_name)-stderr.log
$ sudo supervisorctl reread
$ sudo supervisorctl add hello
$ sudo supervisorctl start hello
PasscodeLock
is the sample project of AppLocker. I took some hours and found how it worked.
The original project used Carthage to manage the framework. It depended Valet
. However, the latest Valet
is 4.x but PasscodeLock
depends 3.x. So we need to specify the version.
pod 'Valet' , '< 4.0'
I switched Carthage to CocoaPods. So I also had to remove the Carthage part in building phase.
// AppALConstants.swift
// MARK: - Keyboard
@IBAction func keyboardPressed(_ sender: UIButton) {
switch sender.tag {
case ALConstants.button.delete.rawValue:
drawing(isNeedClear: true)
case ALConstants.button.cancel.rawValue:
clearView()
dismiss(animated: true) {
self.onSuccessfulDismiss?(nil)
}
default:
drawing(isNeedClear: false, tag: sender.tag)
}
}
private func drawing(isNeedClear: Bool, tag: Int? = nil) { // Fill or cancel fill for indicators
let results = pinIndicators.filter { $0.isNeedClear == isNeedClear }
let pinView = isNeedClear ? results.last : results.first
pinView?.isNeedClear = !isNeedClear
UIView.animate(withDuration: ALConstants.duration, animations: {
pinView?.backgroundColor = isNeedClear ? .clear : .white
}) { _ in
isNeedClear ? self.pin = String(self.pin.dropLast()) : self.pincodeChecker(tag ?? 0)
}
}
private func pincodeChecker(_ pinNumber: Int) {
if pin.count < ALConstants.maxPinLength {
pin.append("\(pinNumber)")
if pin.count == ALConstants.maxPinLength {
switch mode {
case .create:
createModeAction()
case .change:
changeModeAction()
case .deactive:
deactiveModeAction()
case .validate:
validateModeAction()
}
}
}
}
When a user presses a key, private func drawing(isNeedClear: Bool, tag: Int? = nil)
is called.
pinView
is the current indicator. It is set to turn white.func pincodeChecker(_ pinNumber: Int)
is called, the result is pin.