initial commit based on seamlessupdate.app
This commit is contained in:
commit
1f78b34072
17
deploy_static
Executable file
17
deploy_static
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
set -o errexit
|
||||
|
||||
remote=root@grapheneos.org
|
||||
current=$(ssh $remote readlink /var/www/html)
|
||||
|
||||
if [[ $current = html_a ]]; then
|
||||
target=html_b
|
||||
else
|
||||
target=html_a
|
||||
fi
|
||||
|
||||
ssh $remote rm -rf /var/www/$target
|
||||
scp -r static $remote:/var/www/$target
|
||||
ssh $remote chmod -R a+rX /var/www/$target
|
||||
ssh $remote ln -snf $target /var/www/html
|
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
69
static/grapheneos.css
Normal file
69
static/grapheneos.css
Normal file
@ -0,0 +1,69 @@
|
||||
/* use the standard Material Light theme to match the Updater app */
|
||||
/* https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r15/core/res/res/values/colors_material.xml */
|
||||
|
||||
body {
|
||||
font-family: Roboto, sans-serif;
|
||||
background-color: #fafafa; /* grey50 */
|
||||
color: rgba(0, 0, 0, 0.87); /* 87% black */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
font-family: "Roboto Mono", monospace;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
max-width: 800px;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(/roboto_latin.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(/roboto_bold_latin.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto Mono'), local('RobotoMono-Regular'), url(/robotomono_latin.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Mono Bold'), local('RobotoMono-Bold'), url(/robotomono_bold_latin.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
86
static/grapheneos.js
Normal file
86
static/grapheneos.js
Normal file
@ -0,0 +1,86 @@
|
||||
"use strict";
|
||||
|
||||
const devices = ["blueline", "crosshatch", "taimen", "walleye"];
|
||||
const channels = ["stable", "beta"];
|
||||
|
||||
function createLink(href, text) {
|
||||
const link = document.createElement("a");
|
||||
link.appendChild(document.createTextNode(text));
|
||||
link.href = href;
|
||||
return link;
|
||||
}
|
||||
|
||||
function deviceModel(device) {
|
||||
if (device === "blueline") {
|
||||
return "Pixel 3";
|
||||
}
|
||||
if (device === "crosshatch") {
|
||||
return "Pixel 3 XL";
|
||||
}
|
||||
if (device === "marlin") {
|
||||
return "Pixel XL";
|
||||
}
|
||||
if (device === "sailfish") {
|
||||
return "Pixel";
|
||||
}
|
||||
if (device === "taimen") {
|
||||
return "Pixel 2 XL";
|
||||
}
|
||||
if (device === "walleye") {
|
||||
return "Pixel 2";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
for (const channel of channels) {
|
||||
for (const device of devices) {
|
||||
fetch("https://seamlessupdate.app/" + device + "-" + channel).then(response => {
|
||||
if (!response.ok) {
|
||||
return Promise.reject();
|
||||
}
|
||||
return response.text();
|
||||
}).then(text => {
|
||||
const metadata = text.trim().split(" ");
|
||||
const date = new Date(parseInt(metadata[1], 10) * 1000);
|
||||
const dateString = date.toISOString().replace("T", " ").replace("Z", "").split(".")[0];
|
||||
|
||||
const baseUrl = "https://seamlessupdate.app/";
|
||||
|
||||
const factoryFilename = device + "-factory-" + metadata[0] + ".zip";
|
||||
const factoryUrl = baseUrl + factoryFilename;
|
||||
|
||||
const updateFilename = device + "-ota_update-" + metadata[0] + ".zip";
|
||||
const updateUrl = baseUrl + updateFilename;
|
||||
|
||||
const list = document.getElementById(channel);
|
||||
|
||||
const model = deviceModel(device);
|
||||
|
||||
const release = document.createElement("div");
|
||||
release.dataset.model = model;
|
||||
|
||||
const header = document.createElement("h3");
|
||||
header.appendChild(document.createTextNode(model));
|
||||
release.appendChild(header);
|
||||
|
||||
const version = document.createElement("p");
|
||||
version.appendChild(document.createTextNode("Version: " + metadata[2] + "." + metadata[0]));
|
||||
release.appendChild(version);
|
||||
|
||||
release.appendChild(createLink(factoryUrl, factoryFilename));
|
||||
release.appendChild(document.createElement("br"));
|
||||
release.appendChild(createLink(factoryUrl + ".sig", factoryFilename + ".sig"));
|
||||
release.appendChild(document.createElement("br"));
|
||||
release.appendChild(createLink(updateUrl, updateFilename));
|
||||
|
||||
for (const item of list.children) {
|
||||
if (model < item.dataset.model) {
|
||||
list.insertBefore(release, item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
list.appendChild(release);
|
||||
});
|
||||
}
|
||||
}
|
123
static/index.html
Normal file
123
static/index.html
Normal file
@ -0,0 +1,123 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="theme-color" content="#212121"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta name="description" content="GrapheneOS is a security and privacy focused mobile OS with Android app compatibility."/>
|
||||
<title>GrapheneOS</title>
|
||||
<link rel="stylesheet" href="/grapheneos.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<h1>GrapheneOS releases</h1>
|
||||
<p>These are early sample releases of GrapheneOS, an open source privacy and security
|
||||
oriented mobile OS with Android app compatibility. Many past features of the project
|
||||
still need to be ported to the current releases. The project is in the 5th year of
|
||||
development and has been reborn as a non-profit open source project not strongly
|
||||
associated with any specific company or organization. It will take some time for the
|
||||
pieces to come into place turning it into a much broader and more sustainable project
|
||||
with a strong development team. There are multiple organizations and companies in the
|
||||
process of backing this new incarnation of the hardened mobile OS project.</p>
|
||||
<p>See the <a href="https://github.com/GrapheneOS">GitHub organization</a> for sources
|
||||
of the OS sub-projects including the cutting edge
|
||||
<a href="https://github.com/GrapheneOS/hardened_malloc/blob/master/README.md">new
|
||||
hardened memory allocator</a>.</p>
|
||||
<p>These official GrapheneOS releases are supported by the
|
||||
<a href="https://github.com/GrapheneOS/Auditor/releases">Auditor app</a> and
|
||||
<a href="https://attestation.app/">attestation service</a> for hardware-based
|
||||
attestation. For more details, see the <a
|
||||
href="https://attestation.app/about">about page</a> and <a
|
||||
href="https://attestation.app/tutorial">tutorial</a>.</p>
|
||||
<p>The sources are available via the
|
||||
<a href="https://github.com/GrapheneOS/platform_manifest">manifest on GitHub</a>.</p>
|
||||
<p>Bitcoin donations can be sent to 3QpKs45BLXirWAgYtV1sTCbAkfUe7HByR5 to support the
|
||||
project. Alternatively, PayPal donations can be sent to danielmicay@gmail.com (please
|
||||
state that it's a GrapheneOS donation in the payment reason). Other ways of making
|
||||
donations will be provided in the future including donations via a registered charity
|
||||
in the US supporting the project.</p>
|
||||
<h2>Installation</h2>
|
||||
<h3>Prerequisites</h3>
|
||||
<p>You should have at least 2GB of free memory available.</p>
|
||||
<p>You need the unlocked variant of one of the supported devices, not a locked carrier
|
||||
specific variant.</p>
|
||||
<p>You need an updated copy of the <code>fastboot</code> tool and it needs to be
|
||||
included in your <code>PATH</code> environment variable. You can run <code>fastboot
|
||||
--version</code> to determine the current version. It should be at least
|
||||
<code>28.0.0</code>. Don't proceed with the installation process until this is set up
|
||||
properly in your current shell. A very common mistake is using an outdated copy of
|
||||
<code>fastboot</code> from a Linux distribution package not receiving regular updates.
|
||||
Make sure that the <code>fastboot</code> found earliest in your <code>PATH</code> is
|
||||
the correct one if you have multiple copies on your system. You can run <code>which
|
||||
fastboot</code> to determine where the tool being used is coming from. Older versions
|
||||
do not have support for current devices. Very old versions of <code>fastboot</code>
|
||||
from several years ago are still shipped by Linux distributions like Debian and lack
|
||||
the compatibility detection of modern versions so they can soft brick devices.</p>
|
||||
<h3>Enabling OEM unlocking</h3>
|
||||
<p>OEM unlocking needs to be enabled from within the operating system.</p>
|
||||
<p>Enable the developer settings menu by going to Settings -> System -> About phone
|
||||
and pressing on the build number menu entry until developer mode is enabled.</p>
|
||||
<p>Next, go to Settings -> System -> Advanced -> Developer settings and toggle on the
|
||||
'Enable OEM unlocking' setting. This requires internet access on devices with Google
|
||||
Play Services.</p>
|
||||
<h3>Unlocking the bootloader</h3>
|
||||
<p>First, boot into the bootloader interface. You can do this by turning off the
|
||||
device and then turning it on by holding both the Volume Down and Power buttons.</p>
|
||||
<p>The bootloader now needs to be unlocked to allow flashing new images:</p>
|
||||
<pre>fastboot flashing unlock</pre>
|
||||
<p>The command needs to be confirmed on the device.</p>
|
||||
<h3>Obtaining factory images</h3>
|
||||
<p>The initial install will be performed by flashing the factory images. This will
|
||||
replace the existing OS installation and wipe all the existing data.</p>
|
||||
<p>You can download the factory images from the bottom of this page.</p>
|
||||
<p>Verify the official factory images using the GPG signature:</p>
|
||||
<pre>gpg --recv-keys 65EEFE022108E2B708CBFCF7F9E712E59AF5F22A
|
||||
gpg --verify blueline-factory-2018.12.21.18.zip.sig blueline-factory-2018.12.21.18.zip</pre>
|
||||
<p>When this signing key is replaced, the new key will be signed with it.</p>
|
||||
<h3>Flashing factory images</h3>
|
||||
<p>Next, extract the factory images and run the script to flash them. Note that the
|
||||
<code>fastboot</code> command run by the flashing script requires a fair bit of free
|
||||
space in a temporary directory, which defaults to <code>/tmp</code>:<p>
|
||||
<pre>unzip blueline-factory-2018.12.21.18.zip
|
||||
cd blueline-pq1a.181205.006
|
||||
./flash-all.sh</pre>
|
||||
<p>Use a different temporary directory if your <code>/tmp</code> doesn't have enough
|
||||
space available:</p>
|
||||
<pre>mkdir tmp
|
||||
TMPDIR="$PWD/tmp" ./flash-all.sh</pre>
|
||||
<p>Wait for the flashing process to complete and for the device to boot up using the
|
||||
new operating system.</p>
|
||||
<p>You should now proceed to locking the bootloader before using the device as locking
|
||||
wipes the data again.</p>
|
||||
<h3>Locking the bootloader</h3>
|
||||
<p>Locking the bootloader is important as it enables full verified boot. It also prevents using
|
||||
fastboot to flash, format or erase partitions. Verified boot will detect modifications to any of
|
||||
the OS partitions (vbmeta, boot/dtbo, system, vendor) and it will prevent reading any modified /
|
||||
corrupted data. If changes are detected, error correction data is used to attempt to obtain the
|
||||
original data at which point it's verified again which makes verified boot robust to non-malicious
|
||||
corruption.</p>
|
||||
<p>Reboot into the bootloader menu and set it to locked:</p>
|
||||
<pre>fastboot flashing lock</pre>
|
||||
<p>The command needs to be confirmed on the device since it needs to perform a factory
|
||||
reset.</p>
|
||||
<p>Unlocking the bootloader again will perform a factory reset.</p>
|
||||
<h3>Disabling OEM unlocking</h3>
|
||||
<p>OEM unlocking can be disabled again in the developer settings menu within the
|
||||
operating system after booting it up again.</p>
|
||||
<h2>Replacing GrapheneOS with the stock OS</h2>
|
||||
<p>Installation of the stock OS via the stock factory images is the same process
|
||||
described above. However, before locking, there's an additional step to fully revert
|
||||
the device to a clean factory state.</p>
|
||||
<p>The GrapheneOS factory images flash a non-stock Android Verified Boot key which
|
||||
needs to be erased to fully revert back to a stock device state. After flashing the
|
||||
stock factory images and before locking the bootloader, you should erase the custom
|
||||
Android Verified Boot key to untrust it:</p>
|
||||
<pre>fastboot erase avb_custom_key</pre>
|
||||
<h2>Stable channel</h2>
|
||||
<div id="stable"></div>
|
||||
<h2>Beta channel</h2>
|
||||
<div id="beta"></div>
|
||||
<script src="/grapheneos.js"></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
static/roboto_bold_latin.woff2
Normal file
BIN
static/roboto_bold_latin.woff2
Normal file
Binary file not shown.
BIN
static/roboto_latin.woff2
Normal file
BIN
static/roboto_latin.woff2
Normal file
Binary file not shown.
BIN
static/robotomono_bold_latin.woff2
Normal file
BIN
static/robotomono_bold_latin.woff2
Normal file
Binary file not shown.
BIN
static/robotomono_latin.woff2
Normal file
BIN
static/robotomono_latin.woff2
Normal file
Binary file not shown.
2
static/robots.txt
Normal file
2
static/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Sitemap: https://grapheneos.org/sitemap.xml
|
9
static/sitemap.xml
Normal file
9
static/sitemap.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||
<url>
|
||||
<loc>https://grapheneos.org/</loc>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
</urlset>
|
Loading…
x
Reference in New Issue
Block a user