Kurulum ve Ayarlar
Node-RED’i kurmadan önce Raspbian’ın en son sürümüne sahip olduğunuzdan emin olun. Kitabın ilk konularında kullandığınız işletim sisteminin sürümünü öğrenmeyle ilgili bir başlık yer alıyordu. Node-RED’i Raspberry Pi’a kurmak için aşağıdaki komutu verebilirsiniz.
1 |
pi@raspberrypi:~ $ sudo apt-get install nodered |
Node-RED, kurulum için yaklaşık olarak 100MB’lık disk alanına ihtiyaç duyar. Kurulumun tamamlanması biraz zaman alabilir, sabırla bekleyin. Kurulum tamamlandıktan sonra Node-RED’i çalıştırmak için aşağıdaki gibi node-red-pi komutunu verebilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
pi@raspberrypi:~ $ node-red-pi --max-old-space-size=256 29 Jan 11:29:30 - [info] Welcome to Node-RED =================== 29 Jan 11:29:30 - [info] Node-RED version: v1.0.3 29 Jan 11:29:30 - [info] Node.js version: v10.15.2 29 Jan 11:29:30 - [info] Linux 4.19.75-v7l+ arm LE 29 Jan 11:29:32 - [info] Loading palette nodes 29 Jan 11:29:34 - [info] Settings file : /home/pi/.node-red/settings.js 29 Jan 11:29:34 - [info] Context store : 'default' [module=memory] 29 Jan 11:29:34 - [info] User directory : /home/pi/.node-red 29 Jan 11:29:34 - [warn] Projects disabled : editorTheme.projects.enabled=false 29 Jan 11:29:34 - [info] Flows file : /home/pi/.node-red/flows_raspberrypi.json 29 Jan 11:29:34 - [info] Creating new flow file 29 Jan 11:29:34 - [warn] --------------------------------------------------------------------- Your flow credentials file is encrypted using a system-generated key. If the system-generated key is lost for any reason, your credentials file will not be recoverable, you will have to delete it and re-enter your credentials. You should set your own key using the 'credentialSecret' option in your settings file. Node-RED will then re-encrypt your credentials file using your chosen key the next time you deploy a change. --------------------------------------------------------------------- 29 Jan 11:29:34 - [info] Starting flows 29 Jan 11:29:34 - [info] Started flows 29 Jan 11:29:34 - [info] Server now running at http://127.0.0.1:1880/ |
Node-RED çalışmaya başladıktan sonra terminal ortamına yukarıda olduğu gibi günlük (log) kayıtları basar. Bu ekranda iken Node-RED’in çalışmasını sonlandırmak için Ctrl+C tuş bileşimine basabilirsiniz. Ekran çıktısından da görebileceğiniz gibi Node-RED ayarları /home/pi/.node-red/settings.js dosyasında ve kullanıcı projeleri de /home/pi/.node-red dizininde saklamaktadır. Node-RED’in web arabirimine ulaşmak için ise web tarayıcısına http://127.0.0.1:1880/ veya http://raspberrypi.local:1880/ yazabilirsiniz.
Servis olarak çalıştırmak
Önceki başlıkta Node-RED’i terminal ortamında çalıştırmış kapatmak istediğimizde de Ctrl+C tuş bileşiminden faydalanmıştık. Node-RED’i Raspberry Pi’ın açılışında servis olarak çalıştırmak için systemctl aracından faydalanabilirsiniz. Aşağıdaki komutlar ile Node-RED açılışta başlayacak şekilde ayarlanmış ve ardından çalıştırılmıştır.
pi@raspberrypi:~ $ sudo systemctl enable nodered
pi@raspberrypi:~ $ sudo systemctl start nodered
Güvenliğini Artırmak
Varsayılan olarak Node-RED akış düzenleyicisinin güvenliği ayarlanmamıştır. Yani, Raspberry Pi’ın IP adresine ulaşabilen herhangi birisi akış editörüne de erişebilir. Sadece sizin kullanımınıza adanmış bir ağdaysanız bu bir sorun teşkil etmez; fakat ağınız dışarıya açıksa mutlaka güvenlik ayarlarının yapılandırılması gerekir. Node-RED güvenliği, editör ve admin API ile Node’lar ve görüntüleme paneli (dashboard) olarak iki başlıkta incelenebilir.
Kimlik bilgilerini şifrelemek
Node-RED’i ilk defa kurduğunuzda Debug panelinde ve node-red-log aracının çıktısında daima aşağıdaki gibi bir uyarı ile karşılaşırsınız.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Your flow credentials file is encrypted using a system-generated key. If the system-generated key is lost for any reason, your credentials file will not be recoverable, you will have to delete it and re-enter your credentials. You should set your own key using the 'credentialSecret' option in your settings file. Node-RED will then re-encrypt your credentials file using your chosen key the next time you deploy a change. |
Bu uyarının anlamı hassas bilgilerin depolandığı flows_raspberrypi_cred.json dosyasının sistem tarafından oluşturulan bir anahtar ile şifrelendiği, anahtarın bir şekilde (örneğin yeni bir kurulum veya dışarı aktarma) kaybolması ya da değişmesi durumunda ise hassas bilgilerin yeniden tanımlanması gerekeceğidir.
Hassas bilgilerden ne kastedildiğinin açıklamaya çalışalım. Bir akış oluştururken birçok değişik node kullanırsınız ve bu node’ların bazılarına başkaları ile paylaşmak istemeyeceğiniz türden bazı değerler girersiniz. Bunlar node’un kullandığı bir servisin token’ı, kullanıcı adı/parolası veya bağlanılan cihazlarınızın erişim bilgileri gibi bilgiler olabilir. Bunlar programcısı tarafından private (özel) olarak işaretlenmiş node ayarları ya da özellikleridir ve Node-RED tarafından ayrı bir dosyada (flows_raspberrypi_cred.json) şifrelenmiş olarak tutulurlar.
Node-RED’in akışları export menü seçeneği kullanılarak başkaları ile paylaşılmak veya yedeklenmek istendiğinde bu özellik görevini yerine getirir ve node’larda tanımlı özel bilgileriniz şifreli olduğu için başkaları tarafından kullanılamaz. Böyle bir yedek dosyasını aynı bilgisayar üzerinde tekrar içeri (import) aktardığınızda şifreli alanlar yeniden kullanılabilir olur. Çünkü Node-RED şifrelenmiş içeriği deşifre edecek anahtara zaten sahiptir. Bu anahtar kurulum sırasında rastgele oluşturulan bir anahtardır.
Yukarıdaki uyarıda bu anahtarı kendi seçeceğiniz bir anahtar ile değiştirmeniz istenir ve bu durum sürekli olarak hatırlatılır. Diyelim ki akışlarınızı dışarıya yedeklediniz (export) ve yeni bir Raspberry Pi’a aktarmak istiyorsunuz. Uyarıda söylendiği gibi bu anahtarı tanımlamamışsanız private değerleriniz kullanılmaz olur. Bunları tekrar girmeniz gerekir. Dilerseniz bu uyarının gereğini yerine getirelim ve kendinize özel bir anahtar tanımlayalım. Bunu yapmak için settings.js dosyasını açın ve credentialSecret değerini aşağıdaki gibi yorum karakterlerinden (//) kurtarın. Ardından tırnaklar arasına kendi anahtarınızı (“benim-Gizli-Anahtarim”) yazın.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
pi@raspberrypi:~ $ nano ~/.node-red/settings.js [...] // By default, credentials are encrypted in storage using a generated key. To // specify your own secret, set the following property. // If you want to disable encryption of credentials, set this property to false. // Note: once you set this property, do not change it - doing so will prevent // node-red from being able to decrypt your existing credentials and they will be // lost. credentialSecret: "benim-Gizli-Anahtarim", [...] |
Bu anahtarın (“benim-Gizli-Anahtarim”) tanımlandığı herhangi bir Node-RED kurulumunda, bu anahtar ile oluşturulmuş akışlarınızı içeri aktararak yeniden kullanabilirsiniz. Eğer private alanların şifreli olarak kaydedilmesini istemiyorsanız, aşağıdaki gibi false olarak tanımlayabilirsiniz. Bu durumda dışarı aktardığınız akışlarınızda özel bilgilerinizin de yer alacağını unutmayın.
1 2 3 4 5 6 7 |
pi@raspberrypi:~ $ nano ~/.node-red/settings.js [...] credentialSecret: false, [...] |
credentialSecret bir kez tanımlandıktan sonra değiştirilemez. Yeni anahtarınızın geçerli olması için node-red’i aşağıdaki gibi yeniden başlatın ve Deploy edin. Deploy işlemi ilerleyen başlıklarda anlatıldığı üzere düzenleyicide tasarlanan akışların Node-RED engine’a yüklenmesidir.
1 |
pi@raspberrypi:~ $ sudo systemctl node-red restart |
İPUCU: Node-RED’i Yedeklemek
Node-RED üzerinde oluşturduğunuz tüm akışlar flows_raspberrypi.json dosyasında saklanır. credentialSecret’inizi tanımladıktan sonra haricen bir yedek almanız gerektiğinde bu dosyanın ve diğer her şeyin depolandığı ~/.node-red dizini kopyalamak yeterlidir.
Editör ve Admin API’ın güvenliği sağlamak
Akış editörü ve Admin API’ın güvenliğini sağlamak için kullanıcı adı ve parola tanımlaması yapılabilir. Bunun için /home/pi/.node-red/settings.js dosyasında yer alan adminAuth bloğu kullanılır. Dosyayı nano ile açtığınızda aşağıdaki gibi username, password ve persmissions seçeneklerini görebilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
pi@raspberrypi:~ $ nano /home/pi/.node-red/settings.js [..] // Securing Node-RED // ----------------- // To password protect the Node-RED editor and admin API, the following // property can be used. See http://nodered.org/docs/security.html for details. adminAuth: { type: "credentials", sessionExpiryTime: 86400, users: [{ username: "admin", password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", permissions: "*" }] }, [..] |
Öncelikle, normalde // ile devre dışı bırakılan adminAuth dizi bloğunun tüm satırlarındaki // işaretlerini kaldırarak yukarıdakine benzer hale getirin. Kullanıcı adı seçimliktir ve bu örnekte admin kullanılmıştır. Password değeri ise bir bcrypt hash’idir. Seçeceğiniz parolaya ait hash’i buraya girmeniz gerekir. Parolanızın hash’ini oluşturmak için bir dönüştürücüye ihtiyacımız var. Bunun için nmp aracının kullanarak aşağıdaki gibi node-red-admin paketini yükleyin ve ardından araca hash-pw seçeneğini vererek çalıştırın. Sizden bir parola (password) girmenizi isteyecek ve kısa süre içinde girdiğiniz parolanın hash’ini hesaplayarak ekrana basacaktır.
1 2 3 4 5 6 7 |
pi@raspberrypi:~ $ sudo npm install -g node-red-admin pi@raspberrypi:~ $ node-red-admin hash-pw Password: $2a$08$q27eHA0FFjacsJV4G6N5/euXXGivV7F49hhItICOjW9cmR0ylGkY2 |
Son satırdaki $ ile başlayan ve 2 ile biten ifade parolamızın hash kodudur. Bu ifadeyi settings.js içindeki password alanına yapıştırın (tırnak işaretleri arasına yapıştırın) ve kaydederek çıkın. Kullanıcı tanımladığımız bu parola ile oturum açtığında oturumun ne kadar süre açık kalacağı sessionExpiryTime seçeneği ile belirlenir. Saniye cinsinden tanımlanan değer bu örnekte 1 gün (86400) olarak ayarlanmıştır. permissions seçeneği ise akış editörüne erişim sağlayacak kullanıcının erişim düzeyini tanımlar. Bu örnekte kullanılan * işareti kullanıcıya tüm yetkilerin verildiği anlamını taşır. Kullanıcının akış editöründeki akışları görmesini fakat değişiklik yapamamasını sağlamak için read değeri kullanılabilir.
Yaptığınız ayarların geçerli olabilmesi için dosyayı kaydederek çıkın nodered servisini yeniden başlatın. Her şey yolunda gittiyse editör paneli girişinde kullanıcı adı/parola formuyla karşılaşacaksınız.
1 2 3 |
pi@raspberrypi:~ $ sudo systemctl start nodered pi@raspberrypi:~ $ sudo systemctl status nodered |
Node-RED kullanıcı giriş ekranı
Eğer node-red servisi çalışmıyorsa muhtemelen settings.js dosyasında bir hata yaptınız. Servisin neden çalışmadığı ile ilgili detaylı bilgiyi aşağıdaki gibi node-red-log aracını kullanarak görüntüleyebilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
pi@raspberrypi:~ $ node-red-log [..] Error loading settings file: /home/pi/.node-red/settings.js /home/pi/.node-red/settings.js:128 permissions: "*" ^^^^^^^^^^^ SyntaxError: Unexpected identifier [..] |
Yukarıdaki günlük (log) çıktısında /home/pi/.node-red/settings.js dosyasının 128. satırında yazım hatası (SyntaxError) olduğu belirtilmektedir. SyntaxError yazım yanlışı anlamına gelir.
Not: adminAuth dizi bloğunun içindeki users bölümünü kullanarak yeni kullanıcılar eklemeniz mümkündür. Ayrıca, kullanıcı denetimini hâlihazırdaki kimlik doğrulama servisleriniz üzerinden de gerçekleştirebilirsiniz. Güvenlik ayarları ile ilgili detaylı açıklama için sayfanın altındaki URL’i ziyaret edebilirsiniz.[1]
Dashboard’un güvenliğini sağlamak
Dashboard’u yüklediğinizde akışların çıktılarını izlemek için görsel bir arabirime sahip olursunuz. Akış editörü ile beraber dashboard’un güvenliğini bir kullanıcı adı / parola çiftiyle korumak isterseniz settings.js dosyasındaki httpNodeAuth ve httpStaticAuth seçeneklerini ayarlayabilirsiniz. Dosyayı aşağıdaki gibi nano editörü ile açtıktan sonra, ilgili seçeneklerin satır başlarındaki // yorum işaretlerini kaldırın ve ardından kullanıcı adı (user) ile parola (pass) alanlarını önceki başlıkta anlatılana benzer şekilde güncelleyin. Ayarların geçerli olması için node-red’i yeniden başlatmayı unutmayın. Bu ayarları yaptıktan sonra dashboard’u görüntülemek isteyen kişiye kullanıcı adı ve parola sorulacaktır.
1 2 3 4 5 6 7 8 9 |
pi@raspberrypi:~ $ nano /home/pi/.node-red/settings.js [...] httpNodeAuth: {user:"admin",pass:"$2a$08$/l0dztaBljfq…"}, httpStaticAuth: {user:"admin",pass:"$2a$08$/l0dztaBljfqkK…."}, [...] |
Özelleştirilebilir Dashboard Login Formu
Node-RED, dashboard güvenliği için HTTP Basic Authentication yöntemini kullanır. Bu HTTP protokolü içinde tanımlanmış bir kimlik doğrulama yöntemidir ve kullanıcı girişi için açılan formu web tarayıcısının kendisi sağlar. Dilerseniz bu giriş formunu dashboard’un kendi node’larını kullanarak daha görsel şekilde kendiniz de tasarlayabilirsiniz. İlgili formun JSON kodlarını indirmek için şu adresi ziyaret edin: https://github.com/phyunsj/node-red-dashboard-login
Belleği artırmak
Node-RED’i SystemD aracılığıyla bir servis olarak çalıştırdığımız uygulamalarımızda Node-RED’in ihtiyaç duyduğu bellek miktarını önceden hazır etmek için ilgili servisin yapılandırma dosyasını kullanabilirsiniz. /lib/systemd/system/nodered.service servis dosyasına aşağıdaki seçeneği ekleyip açılışta daha fazla bellek tahsis etmesini sağlayabilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 |
pi@raspberrypi:~ $ sudo nano /lib/systemd/system/nodered.service [Service] Environment="PI_NODE_OPTIONS=--max_old_space_size=256" Dosyayı düzenledikten sonra ayarın geçerli olabilmesi için aşağıdaki komutları çalıştırabilirsiniz: pi@raspberrypi:~ $ sudo systemctl daemon-reload pi@raspberrypi:~ $ sudo systemctl restart nodered |
Environment seçeneğinin aldığı max_old_space_size argümanı Node-RED’in ihtiyaç duyduğu belleğin önceden tahsis edilmesini sağlar. Özellikle sistem kaynakları sınırlı Raspberry Pi gibi donanımlar üzerinde bu tahsisin bildirilmesi önemlidir, aksi takdirde yeterli bellek bulunamadığında Node-RED’in çalışması kontrolsüz olarak sonlanacaktır. Node-RED üzerinde çalıştıracağınız uygulamaların büyüklüğüne göre bellek miktarını artırabilirsiniz. 256MB çoğu uygulama için yeterli olacaktır.
Servis port numaralarını değiştirmek
Dilerseniz Node-RED’in varsayılan port numarası olan 1880’i değiştirebilirsiniz. Bunun için settings.js dosyasında yer alan uiPort özelliğini kullanabilirsiniz. Dosyayı nano editörü ile açarak ilgili değeri değiştirin ve Node-RED servisini yeniden başlatın.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
pi@raspberrypi:~ $ nano ~/.node-red/settings.js […] module.exports = { // the tcp port that the Node-RED web server is listening on uiPort: process.env.PORT || 1881, […] pi@raspberrypi:~ $ sudo systemctl restart nodered |
Yukarıdaki örnek yapılandırmada Node-RED’in port numarası 1881 olarak değiştirilmiştir. Node-RED varsayılan olarak çalıştığı bilgisayarın tüm ağ arabirimlerini ve IP adreslerini dinler. Sadece belli bir IP adresini dinlemesini istiyorsanız settings.js dosyasındaki uiHost özelliğini etkinleştirerek bir IP adresi atayabilirsiniz.
Birden fazla kopya çalıştırmak
Dilerseniz aynı bilgisayar üzerinde Node-RED’in birden fazla kopyasını çalıştırabilirsiniz. Bazen üzerinde çalışılan projeleri birbirinden ayırarak bağımsız olarak geliştirmek veya Node-RED’in yeni bir kopyasının kullanımını başkasının sunmak için bu gerekli olabilir. Bu başlıkta Node-RED’i yapılandırarak iki kopyasının aynı Raspberry Pi bilgisayarı üzerinde farklı port’ları kullanarak çalışmasını sağlayacağız. Node-RED’in birden fazla kopyasının çalışabilmesi için öncelikle her bir kopyanın kendi settings.js dosyasını kullanması sağlamak ve her dosyadaki port numarası (uiPort) yapılandırmasının çakışma yapmayacak şekilde yapılandırılması gerekir. Birinci kopyamız 1880 port’unu diğeri de 1770 port’unu kullanacak. Ayrıca her kopya kendi bağımsız akış koduna sahip olacağı için akış kodlarının, eklentilerin ve kütüphanenin saklandığı kullanıcı dizinin de yeni bir kopyasının oluşturulması gerekir. Node-RED’in tüm bu kullanıcı dosyalarını ve ayarlarını tuttuğu dizin ~/.node-red’dir. settings.js ana ayar dosyası da bu dizin içindedir.
Dilerseniz öncelikle Node-RED’i durduralım ve referans olarak kullanacağımız orijinal kullanıcı dizininin bir kopyasını üretelim. Yeni kopyanın konumu şu olacak ~/.node-red-2 Bunun için cp komutundan aşağıdaki gibi faydalanabiliriz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
pi@raspberrypi:~ $ sudo systemctl stop nodered pi@raspberrypi:~ $ cp -r .node-red/ .node-red-2 Şimdi de ~/.node-red-2/settings.js dosyasını düzenlemek üzere açalım ve aşağıdaki değişiklikleri yapalım: pi@raspberrypi:~ $ nano ~/.node-red-2/settings.js […] module.exports = { // the tcp port that the Node-RED web server is listening on uiPort: process.env.PORT || 1770, […] // By default, all user data is stored in a directory called `.node-red` under // the user's home directory. To use a different location, the following // property can be used userDir: '/home/pi/.node-red-2/', […] |
Yeni yapılandırma dosyamızda 2 değişiklik yaptık. Kullanıcı arabiriminin port numarasını (uiPort) 1770 ve kullanıcı dizinini de (userDir) /home/pi/.node-red-2 olarak ayarladık.
Kitapta anlatılan yapılandırmada nodered servisi SystemD’nin kontrolündedir ve systemctl aracı ile yönetilmektedir. Dilerseniz şimdi yeni oluşturduğumuz kopya için de bir SystemD servisi yapılandırması tanımlayalım. Bu konuda detaylı bilgiyi kitabın “Yeni bir SystemD servisi oluşturmak” başlığında bulabilirsiniz. Hâlihazırda var olan /lib/systemd/system/nodered.service birim dosyasının nodered2 ismi ile bir kopyasını üreterek işe başlayabiliriz. Yeni servisimizin adı nodere2 olacak.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
pi@raspberrypi:~ $ sudo cp /lib/systemd/system/nodered.service /lib/systemd/system/nodered2.service Ardından yeni dosyamızı nano editörü ile aşağıdaki gibi düzenleyelim. pi@raspberrypi:~ $ sudo nano /lib/systemd/system/nodered2.service # systemd service file to start Node-RED [Unit] Description=Node-RED yeni kopya […] [Service] […] Environment="NODE_OPTIONS=--max_old_space_size=256" # uncomment and edit next line if you need an http proxy #Environment="HTTP_PROXY=my.httpproxy.server.address" # uncomment the next line for a more verbose log output Environment="NODE_RED_OPTIONS=--settings /home/pi/.node-red-2/settings.js" […] |
Yukarıdaki yapılandırma dosyasında temel olarak sadece NODE_RED_OPTIONS satırını eklemiş olduk. Dosyayı kaydedip çıktıktan sonra aşağıdaki komutları çalıştırın.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
pi@raspberrypi:~ $ sudo systemctl daemon-reload pi@raspberrypi:~ $ sudo systemctl start nodered pi@raspberrypi:~ $ sudo systemctl start nodered2 pi@raspberrypi:~ $ sudo systemctl status nodered2 ● nodered2.service - Node-RED yeni kopya Loaded: loaded (/lib/systemd/system/nodered2.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2020-04-10 02:52:11 +03; 3s ago Docs: http://nodered.org/docs/hardware/raspberrypi.html Main PID: 3045 (node) Tasks: 7 (limit: 2200) Memory: 12.1M CGroup: /system.slice/nodered2.service └─3045 node --max_old_space_size=256 /usr/lib/node_modules/node-red/bin/../red.js --settings /home/pi/.node-red-2/settings.js Nis 10 02:52:11 raspberrypi systemd[1]: Started Node-RED yeni kopya. |
Eğer her şey yolunda gittiyse artık 1880 ve 1770 numaralı HTTP port’larından çalışan iki farklı Node-RED’e sahibiz. Web tarayıcısına bu port’ları yazarak yapılandırmayı sınayabilirsiniz.
Node-RED araçlarından biri olan node-red-log Node-RED’in günlük kayıtlarını görüntülemek için kullanılır. Esasında bu araç /usr/bin/node-red-log konumunda yer alan bir betiktir ve journalctl aracını kullanarak nodered servisinin çıktısını okur. Yeni kopyanın günlük mesajlarını görüntülemek için aşağıdaki komutu nodered2 servis adıyla çalıştırabilirsiniz.
1 |
pi@raspberrypi:~ $ journalctl -f -n 20 -u nodered2 -o cat |
[1] Node-RED Güvenlik Ayarları – http://nodered.org/docs/security.html