Packaging guideline - ReadyNAS/sdk GitHub Wiki

Summary

  • Read NasApplicationsSpec.md and follow the guidelines.
  • If your application uses systemd to control service start/stop, your unit name must be fvapp-[AppName].service. If not, include an empty ServiceName tag. For example, <ServiceName/>. (See sample 2)
  • Your postinst must contain systemctl restart apache2.service. (Older documentation that said to use reload-or-restart was wrong.)
  • You can optionally enable and/or start your application from postinst. Otherwise, installation of your application will NOT be enabled or started. For example, you can add systemctl start fvapp-sample1.service and systemctl enable fvapp-sample1.service in postinst.
  • Your prerm must stop and disable the service if you use systemd service.

API to talk with readynasd

From script languages such as bash, php, perl, etc, you can use command line utility /usr/bin/rn_nml to send minimum set of NML in simple form.

For example, if you want to get the Serial Number of the device, you can use rn_nml -g systeminfo | xmllint --xpath /SystemInfo/Model/text\(\) -. Please note, xmllint is in the libxml2-utils package. So if you want to use the xmllint command, your app must use the libxml2-utils package.

# mymodel=$(rn_nml -g systeminfo | xmllint --xpath '/SystemInfo/Model/text()' -)
# echo $mymodel
ReadyNAS 314

rn_nml -g systeminfo

This command returns all system info, including serial number and model.

# rn_nml -g systeminfo
<?xml version="1.0" encoding="UTF-8"?>
<SystemInfo>
  <Model>ReadyNAS 314</Model>
  <Serial>3C312A0J0010A</Serial>
  <Firmware_Name>ReadyNASOS</Firmware_Name>
  <Firmware_Version>6.0.1-T1089</Firmware_Version>
  <Memory>1024</Memory>
  <CPU_Number>4</CPU_Number>
  <CPU_Frequency>2127.915039</CPU_Frequency>
  <MAC_Address>84:1B:5E:26:D7:10,84:1B:5E:26:D7:11</MAC_Address>
  <Language>en_us</Language>
  <Raid_Level>zfs</Raid_Level>
  <HDD_Vendor/>
  <HDD_Model/>
  <HDD_Serial/>
  <HDD_Firmware/>
  <Registered>0</Registered>
  <Raid/>
  <Anti-Virus-Def-Version>not enabled</Anti-Virus-Def-Version>
  <Anti-Virus-Last-Updated>2013020018</Anti-Virus-Last-Updated>
</SystemInfo>

rn_nml -g shares

This command returns all shares in simple form. For detailed listing, use rn_nml -g shares-detail instead.

# rn_nml -g shares
<?xml version="1.0" encoding="UTF-8"?>
<Share_Collection>
  <Share id="data/Backup" resource-id="data/Backup" resource-type="SimpleShare" share-name="Backup"/>
  <Share id="data/Documents" resource-id="data/Documents" resource-type="SimpleShare" share-name="Documents"/>
  <Share id="data/Music" resource-id="data/Music" resource-type="SimpleShare" share-name="Music"/>
  <Share id="data/Pictures" resource-id="data/Pictures" resource-type="SimpleShare" share-name="Pictures"/>
  <Share id="data/Videos" resource-id="data/Videos" resource-type="SimpleShare" share-name="Videos"/>
  <Share id="data/南京" resource-id="data/南京" resource-type="SimpleShare" share-name="南京"/>
</Share_Collection>

rn_nml -g shares-detail

NOTE: This output format is subject to change without notice.

This command returns all shares in detailed form. For simple parsing purpose, it is recommended to use rn_nml -g shares instead.

# rn_nml -g shares-detail
<?xml version="1.0" encoding="UTF-8"?>
<Share_Collection>
  <Share id="data/Backup" resource-id="data/Backup" resource-type="Share">
    <Folder_Owner>
      <Access>ReadWrite</Access>
      <System_User id="99" resource-id="99" resource-type="System_User">
        <User_Id>99</User_Id>
        <User_Name>guest</User_Name>
      </System_User>
    </Folder_Owner>
    <Folder_Group>
      <Access>ReadWrite</Access>
      <System_Group id="99" resource-id="99" resource-type="System_Group">
        <Group_Id>99</Group_Id>
        <Group_Name><![CDATA[guest]]></Group_Name>
      </System_Group>
    </Folder_Group>
    <Folder_Everyone>
      <Access>ReadWrite</Access>
    </Folder_Everyone>
    <Access_Acl_List>
      <acl tag="user-obj" perm="7"/>
      <acl account="98" tag="user" perm="7"/>
      <acl account="99" tag="user" perm="7"/>
      <acl tag="group-obj" perm="7"/>
      <acl account="98" tag="group" perm="7"/>
      <acl account="99" tag="group" perm="7"/>
      <acl tag="mask" perm="7"/>
      <acl tag="other" perm="7"/>
    </Access_Acl_List>
    <Default_Acl_List>
      <acl tag="user-obj" perm="7"/>
      <acl account="98" tag="user" perm="7"/>
      <acl account="99" tag="user" perm="7"/>
      <acl tag="group-obj" perm="7"/>
      <acl account="98" tag="group" perm="7"/>
      <acl account="99" tag="group" perm="7"/>
      <acl tag="mask" perm="7"/>
      <acl tag="other" perm="7"/>
    </Default_Acl_List>
    <Protocol_List>
      <cifs id="0" resource-id="0" protocol-id="1" resource-type="cifs">
        <Group_List/>
        <Host_List/>
        <User_List/>
        <DFS_List/>
        <Property_List>
          <Not_Available>0</Not_Available>
          <Share_Display_Option>0</Share_Display_Option>
          <Enable_Oplocks>0</Enable_Oplocks>
          <Enable_Recycle_Bin>0</Enable_Recycle_Bin>
          <Recycle_Size_Limit>0</Recycle_Size_Limit>
          <Recycle_Age_Limit>25000</Recycle_Age_Limit>
          <Default_Access>ReadWrite</Default_Access>
          <Allow_Guest_Access>1</Allow_Guest_Access>
          <New_File_Folder_Perm_Autoset>1</New_File_Folder_Perm_Autoset>
          <Acl_Change_Restriction_Toggle>0</Acl_Change_Restriction_Toggle>
          <Folder_Create_Group_Rights>ReadWrite</Folder_Create_Group_Rights>
          <Folder_Create_EveryOne_Rights>ReadWrite</Folder_Create_EveryOne_Rights>
          <File_Create_Group_Rights>ReadWrite</File_Create_Group_Rights>
          <File_Create_EveryOne_Rights>ReadWrite</File_Create_EveryOne_Rights>
          <Enable_DFS>0</Enable_DFS>
        </Property_List>
      </cifs>
   ..... deleted by editor .....

rn_nml -g volumes

This command returns all internal volumes. For detailed information (such as volume size), use rn_nml -g volumes-detail instead.

# rn_nml -g volumes
<?xml version="1.0" encoding="UTF-8"?>
<Volume_Collection>
  <Volume resource-id="MyVolume" resource-type="Volume"/>
  <Volume resource-id="data" resource-type="Volume"/>
</Volume_Collection>

rn_nml -g volumes-detail

NOTE: This output format is subject to change without notice.

This command returns all internal volumes with detailed information. For simple listing, use rn_nml -g volumes instead.

# rn_nml -g volumes-detail
<?xml version="1.0" encoding="UTF-8"?>
<Volume_Collection>
  <Volume resource-id="data" resource-type="Volume" ejectable="false">
    <Property_List>
      <Volume_Name>data</Volume_Name>
      <Volume_Mode>1</Volume_Mode>
      <AltRoot/>
      <DeDup/>
      <AutoExpand>on</AutoExpand>
      <AutoReplace>on</AutoReplace>
      <CacheFile/>
      <Delegation>on</Delegation>
      <ListSnapshots>on</ListSnapshots>
      <Version>0</Version>
      <Allocated>70190504</Allocated>
      <Capacity>70190504</Capacity>
      <Free>70182876</Free>
      <Available>70182876</Available>
      <GUID>e738b302-236b-48b6-a3f7-af38c00007bd</GUID>
      <Health>UNPROTECTED</Health>
      <Checksum>on</Checksum>
    </Property_List>
    <vdev_list>
      <RAID LEVEL="1" ID="0">
        <Disk resource-id="sda"/>
      </RAID>
    </vdev_list>
  </Volume>
</Volume_Collection>

rn_nml -a share:/volname/sharename

Send <add> with resource-type="Share_Collection". This command adds one share whose name is sharename under the volume named volname. Allows CIFS and AFP access. Access using the other protocols will be disabled. As a special case, if volname is *, then a share is created on the volume selected by readynasd.

rn_nml -a share:/volname/sharename:opts
rn_nml -a share:/volname/sharename

Same as above, except this command can specify which protocol is enabled by comma separated form. Valid protocols are cifs, afp, nfs and ftp. You can use * as volname.

# rn_nml -a share:/data/MyShare           ... create share with cifs and afp enabled     
# rn_nml -a share:/data/MyShare:cifs      ... create share with only cifs enabled     
# rn_nml -a share:/data/MyShare:ftp,nfs   ... create share with ftp and nfs enabled     
# rn_nml -a 'share:/*/MyShare'            ... create share with cifs and afp enabled on default volume     

rn_nml -a share:/volname/sharename

rn_nml -s share:/volname/sharename:opts
rn_nml -s share:/volname/sharename

Similar to 'rn_nml -a', but this command sets options for an existing share.

# rn_nml -s share:/data/MyShare           ... set share with cifs and afp enabled     
# rn_nml -s share:/data/MyShare:cifs      ... set share with only cifs enabled     
# rn_nml -s share:/data/MyShare:ftp,nfs   ... set share with ftp and nfs enabled     
# rn_nml -s share:/data/MyShare:          ... set share with all protocol disabled

Protocol specific options can be included. Currently default access and host-based ACL can be set.

# rn_nml -s share:/data/MyShare:protocol{protocolopts}

The protocolopts is form paramname=(paramvalue).

paramname paramvalue
default default access, one of Disabled, ReadOnly or ReadWrite.
hostacl triplet of hostspec, access, root_privilege.
If do not want to change for the particular protocols, use {}. Below is example to set NFS for ReadOnly for default, and specify host specific access control. Other protocols remain unchanged.
# ./rn_nml -s 'share:/data/Videos:cifs{},afp{},nfs{default=(ReadOnly),hostacl=(10.20.0.25,ReadWrite,0),hostacl=(10.20.0.20,ReadWrite,1)},ftp{}'

rn_nml -a shareUsedBy:/volname/sharename=appname

This command marks a share that is used by appname. If share is UsedBy appname and the /apps/{appname}/etc/samba.include file exists, then smb.conf includes the share within the [sharename] section. If samba.include does not exist, the following files are searched in the order listed below and the first file found is included instead. {Arch} is either x86_64 or arm. {ShareName} is the sharename.

  /apps/{appname}/etc/samba.include
  /apps/{appname}/etc/samba.include.{Arch}
  /apps/{appname}/etc/samba.include.{ShareName}.{Arch}

Example follows.

# rn_nml -a shareUsedBy:/data/MyShare=myapp

rn_nml -d share:/volname/sharename

This command deletes the specified share.

root@nas-26-D7-10:~# rn_nml -g shares
<?xml version="1.0" encoding="UTF-8"?>
<Share_Collection>
  <Share id="data/Backup" resource-id="data/Backup" resource-type="SimpleShare" share-name="Backup"/>
  <Share id="data/Documents" resource-id="data/Documents" resource-type="SimpleShare" share-name="Documents"/>
  <Share id="data/Music" resource-id="data/Music" resource-type="SimpleShare" share-name="Music"/>
  <Share id="data/Pictures" resource-id="data/Pictures" resource-type="SimpleShare" share-name="Pictures"/>
  <Share id="data/Videos" resource-id="data/Videos" resource-type="SimpleShare" share-name="Videos"/>
  <Share id="data/ι«˜ε…ˆη”Ÿ" resource-id="data/ι«˜ε…ˆη”Ÿ" resource-type="SimpleShare" share-name="ι«˜ε…ˆη”Ÿ"/>
</Share_Collection>
root@nas-26-D7-10:~# rn_nml -d share:/data/ι«˜ε…ˆη”Ÿ
root@nas-26-D7-10:~# rn_nml -g shares
<?xml version="1.0" encoding="UTF-8"?>
<Share_Collection>
  <Share id="data/Backup" resource-id="data/Backup" resource-type="SimpleShare" share-name="Backup"/>
  <Share id="data/Documents" resource-id="data/Documents" resource-type="SimpleShare" share-name="Documents"/>
  <Share id="data/Music" resource-id="data/Music" resource-type="SimpleShare" share-name="Music"/>
  <Share id="data/Pictures" resource-id="data/Pictures" resource-type="SimpleShare" share-name="Pictures"/>
  <Share id="data/Videos" resource-id="data/Videos" resource-type="SimpleShare" share-name="Videos"/>
</Share_Collection>

rn_nml -d shareUsedBy:/volname/sharename=appname This command unmarks a share that is used by appname.

# rn_nml -a shareUsedBy:/data/MyShare=myapp

rn_nml -a user:username:primarygroup

rn_nml -a user:username:primarygroup:b64pass

rn_nml -a user:username:primarygroup:b64pass:uid This command adds a new user. b64pass is base64 encoded plain password. Two examples are shown below. The first example creates user account r2d2 whose primary group is jedi, password is StarWars, and uid is 1962. The second example does not specify uid.

# rn_nml -a user:r2d2:jedi:$(echo -n StarWars | base64):1962
# rn_nml -a user:r2d2:jedi:$(echo -n StarWars | base64)

rn_nml -g users

This command lists all users in NML.

# rn_nml -g users

rn_nml -s user:uid:b64pass

rn_nml -s user:uid:b64pass:primarygroup This command changes user password and primary group.

# rn_nml -s user:1963:$(echo -n DarthVader | base64)
# rn_nml -s user:1963:$(echo -n DarthVader | base64):droid

rn_nml -d user:uid

This command deletes the user identified by uid.

# rn_nml -d user:1962

rn_nml -a group:groupname

rn_nml -a group:groupname:gid This command adds a new group. Two examples are shown below. The first example creates the group account jedi whose gid is 2013. The second example does not specify gid.

# rn_nml -a group:jedi:2013
# rn_nml -a group:jedi

rn_nml -g groups

This command lists all groups in NML.

# rn_nml -g groups

rn_nml -d group:gid

This command deletes the group identified by gid.

# rn_nml -d group:2013

rn_nml -i path-to-deb-pkg

This command installs a Debian package. path-to-deb-pkg is absolute path to the local Debian package file, whose extension is .deb.

rn_nml -I pkgname.deb

Same as above, but ignores verifying signature.

rn_nml -S [AppName]

This command sends <set> with resource-type="LocalApp", resource-id="Application", and state="running". This command will eventually call systemctl start fvapp-[AppName].service and systemctl enable fvapp-AppName].service.

rn_nml -K [AppName]

This command sends <set> with resource-type="LocalApp", resource-id="Application", and state="stopped". This command will eventually call systemctl stop fvapp-[AppName].service and systemctl disable fvapp-AppName].service.

rn_shutdown

This command shuts down and powers off the system.

rn_shutdown -r

This command shuts down and reboots the system.

event_push app readynasd '<add-s resource-type="LocalApp" resource-id="LocalApp"><LocalApp appname="sample1" success="0" reboot="0"/></add-s>' 0 0

This command sends an event to readynasd for app installation complete. Default value of success and reboot is 0. 0 is false. When success=0, then reboot flag is ignored. If success=1 and reboot=1, then the appropriate message will display in a pop-up window.

event_push app readynasd '<delete-s resource-type="LocalApp" resource-id="LocalApp"><LocalApp appname="sample1" success="0" reboot="0"/></delete-s>' 0 0

This command sends an event to readynasd for app un-installation complete. Default value of success and reboot is 0. 0 is false. When success=0, then reboot flag is ignored. If success=1 and reboot=1, then the appropriate message will display in a pop-up window.

Debian (ReadyNAS) User Defined Feilds

ReadyNAS OS 6.7.0 has added a newer feature to allow app developers to use existing third-party debian repositories within their app. This will help the developer provide the newer apps based on updates that may not exist in the Debian Jessie's repo and/or would require a more manual intervention.

The new configuration allowed for the ReadyNAS App developers is located within the debian control file. At the end of the control file you are able to add the following user defined fields:

XB-Repo:
XB-Repo-Key-Url:
XB-Repo-Keyserver:
XB-Repo-Key-ID:
  • XB-Repo contains the string that you would have in your /etc/apt/source.d/x.list
  • XB-Repo-Key-Url contains a link to the gpg key file information.
  • XB-Repo-Keyserver is optional and it can contain the repo’s referenced key server.
  • XB-Repo-Key-ID contains the key id that would work with the key server.

The ReadyNAS will look at these fields, apply the configuration settings, update the apt list, then run the updated apt ReadyNAS app installation.

The following is an example o how a control file would look:

Source: nodejs-app
Section: contrib
Priority: extra
Maintainer: Dev ReadyNAS <[email protected]>
Build-Depends: debhelper (>= 8.0.0)
Standards-Version: 3.9.8
Homepage: https://nodejs.org/

Package: nodejs-app
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, readynasos (>= 6.7.0~T158), nodejs (>= 6.9.0)
Conflicts: nodejs (>=7.0.0)
Description: NodeJS App for ReadyNAS
XB-Repo: deb https://deb.nodesource.com/node_6.x jessie main
XB-Repo-Key-Url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key

NodeJS App Repo Example

Note: To help ensure ReadyNAS root volumes are kept at a manageable capacity. We would urge developers to keep the app dependencies under 100MB. Depending on what the installed applications.

⚠️ **GitHub.com Fallback** ⚠️